Компонент View в Django отвечает за обработку HTTP-запросов и формирование ответов.
View может выглядеть как функция или класс, в который входит запрос и выходит ответ
Из статьи ты узнаешь, как обрабатывается запрос в Django и как реализацию этого механизма можно использовать для упрощения кода приложения. Затронем как внутреннюю реализацию, так и "базу" — разные способы написания View.
Как работает View
View — далеко не первый элемент в цепочке обработки запроса:
HTTP Request → Request Middlewares → URL Router → View → ... → Template Renders → Response Middlewares → HTTP Response
- Request Middlewares — запускает каждый из
settings.MIDDLEWARE
Middleware для входной обработки запроса - URL Router (URL Dispatcher) — определяет какой View будет обрабатывать запрос (на основе URL в запросе)
- Views — логика обработки
- Template Renderers — рендеринг шаблона
- 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)
Где важны такие части:
- При настройке URL Router (обычно в файле
urls.py
) идет сопоставление URL и функции (View.as_view.view
) - Для каждого запроса эта функция создает новый экземпляр
View
и заполняются данные запросаView.setup
- Уже после этого определяется, какой именно метод обработает запрос
View.dispatch
, и запускает его - Обычно метод выбирается на основе HTTP-глагола
Такое разделение позволяет прямо на уровне View.dispatch
(до обработки запроса) проверить доступ к ресурсу и ответить ошибкой. Эту возможность рассмотрим в следующих материалах.