Компонент View в Django отвечает за обработку HTTP-запросов и формирование ответов.

View может выглядеть как функция или класс, в который входит запрос и выходит ответ

Из статьи ты узнаешь, как обрабатывается запрос в Django и как реализацию этого механизма можно использовать для упрощения кода приложения. Затронем как внутреннюю реализацию, так и "базу" — разные способы написания View.

Как работает View

View — далеко не первый элемент в цепочке обработки запроса:

HTTP Request → Request Middlewares → URL Router → View → ... → Template Renders → Response Middlewares → HTTP Response
  1. Request Middlewares — запускает каждый из settings.MIDDLEWARE Middleware для входной обработки запроса
  2. URL Router (URL Dispatcher) — определяет какой View будет обрабатывать запрос (на основе URL в запросе)
  3. Views — логика обработки
  4. Template Renderers — рендеринг шаблона
  5. Response Middlewares — в обратном порядке запускает settings.MIDDLEWARE для финальной обработки запроса

Таким образом, есть как минимум 6 точек, где можно разместить код обработки запроса. Можно изменить как входные данные (например, добавить свой уникальный operation_id для логирования), так и выходные (например, сделать анонимизацию выходных данных).

Все это возможно, потому что Django использует callable-based подход для всего подряд. Достаточно, чтобы в объекте был метод __call__, и тогда его можно использовать как в роли View, так и в роли Middleware.

Можно реализовать только __call__, но лучше реализовывать более понятные as_view, process_request и другие, в зависимости от класса объекта.

На практике для реализации View используют такой интерфейс:

# django/views/generic/base.py (код упрощен)
class View:
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

    def as_view(cls, **initkwargs):
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            self.setup(request, *args, **kwargs)
            return self.dispatch(request, *args, **kwargs)

        return view

    def dispatch(self, request, *args, **kwargs):
        # Определяет, какой HTTP метод обрабатывать
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        return handler(request, *args, **kwargs)

Где важны такие части:

  1. При настройке URL Router (обычно в файле urls.py) идет сопоставление URL и функции (View.as_view.view)
  2. Для каждого запроса эта функция создает новый экземпляр View и заполняются данные запроса View.setup
  3. Уже после этого определяется, какой именно метод обработает запрос View.dispatch, и запускает его
  4. Обычно метод выбирается на основе HTTP-глагола

Такое разделение позволяет прямо на уровне View.dispatch (до обработки запроса) проверить доступ к ресурсу и ответить ошибкой. Эту возможность рассмотрим в следующих материалах.

Виды View в Django

Получить доступ к полному материалу
Полный текст доступен в курсе