Путь от request до response в Джанго

Веб-приложение или веб-сайт вращаются вокруг цикла запрос-ответ, и приложения Django не являются исключением. Но это не просто двухэтапный процесс. Наши приложения Django должны пройти различные стадии, чтобы вернуть конечному пользователю результат. Чтобы лучше понять структуру Django, мы должны понимать, как инициируются запросы и как конечный результат передается конечному пользователю. В следующих разделах я собираюсь объяснить различные этапы запросов и используемое там программное обеспечение или код.

При настройке нового проекта Django первое, что вы сделаете, это подключите ваши URLconfs и создадите какие-то представления. Но что на самом деле происходит «под капотом»? Как Django направляет трафик к представлению и какую роль играют промежуточное ПО (middleware) в этом цикле?

WSGI

Как мы знаем, веб-сервер - это программа, которая использует HTTP (протокол передачи гипертекста) для предоставления пользователям данных, формирующих веб-страницы, в ответ на их запросы, которые пересылаются HTTP-клиентами их компьютеров.

WSGI — это инструмент, созданный для решения основной проблемы: подключения веб-сервера к веб-среде. WSGI имеет две стороны: «серверная» и «прикладная». Для обработки ответа WSGI сервер выполняет приложение и предоставляет функцию обратного вызова на стороне приложения. Приложение обрабатывает запрос и возвращает ответ на сервер, используя предоставленный обратный вызов. По сути, обработчик WSGI действует как привратник между вашим веб-сервером (Apache, NGINX и т.д.) и вашим проектом на Django.

Между сервером и приложением лежат промежуточные программы (middleware). Вы можете думать о промежуточном программном обеспечении как о серии двунаправленных фильтров: они могут изменять (или замыкать) данные, передаваемые назад и вперед между сетью и вашим приложением Django.

Большая картина — поток данных

Когда пользователь делает запрос к вашему приложению, создается экземпляр обработчика WSGI, который:

  1. Импортирует ваш файл settings.py и классы исключений Django.
  2. Загружает все промежуточные классы, которые он находит в кортеже MIDDLEWARE_CLASSES или MIDDLEWARES (в зависимости от версии Django), расположенном в settings.py
  3. Создает четыре списка методов, которые обрабатывают запрос, представление, ответ и исключения.
  4. Перебирает методы запроса, выполняя их по порядку
  5. Определяет запрошенный URL
  6. Проходит через каждый из методов обработки представления
  7. Вызывает функцию отображения (обычно рендеринг шаблона)
  8. Обрабатывает любые методы исключения
  9. Проходит через каждый из методов ответа (изнутри, в обратном порядке из промежуточного ПО запроса)
  10. Наконец, создает возвращаемое значение и вызывает функцию обратного вызова на веб-сервере

Давайте начнем.

Слои приложения Джанго

  1. Request Middlewares - Запрос промежуточного программного обеспечения
  2. URL Router (URL Dispatcher) - Маршрутизация URL
  3. Views - Отображения
  4. Context Processors - Контекстные процессоры
  5. Template Renderers - Рендер шаблонов
  6. Response Middlewares - Промежуточное программное обеспечение ответа

Всякий раз, когда поступает запрос, он обрабатывается промежуточным программным обеспечением. Мы можем иметь несколько промежуточных программ. Найти их можно в настройках проекта (settings.py). Промежуточное ПО запросов Django происходит по порядку при обработке запроса. Предположим, что если у нас есть запрос промежуточного программного обеспечения в порядке A, B, C, то запрос сначала обрабатывается промежуточным программным обеспечением A, а затем B, а затем C. Django предлагает связку промежуточного программного обеспечения по умолчанию. Мы также можем написать наши собственные или пользовательские промежуточные программы. После обработки запроса промежуточным программным обеспечением он будет отправлен на маршрутизатор URL (диспетчер URL).

URL-маршрутизатор примет запрос от промежуточного программного обеспечения запроса (request middleware) и получит путь URL-адреса из запроса. На основе пути URL-маршрутизатор попытается сопоставить путь запроса с доступными шаблонами URL-адреса. Эти шаблоны URL имеют форму регулярных выражений. После сопоставления пути URL с доступными шаблонами URL запрос будет отправлен в представление, связанное с URL.

Теперь мы находимся в слое бизнес-логики. Представления обрабатывают бизнес-логику, используя запрос и данные запроса (данные, отправленные в GET, POST и т.д.). После обработки в представлении запрос отправляется контекстным процессорам, с помощью обработчиков контекста запроса добавляет контекстные данные, которые помогут средству визуализации шаблонов визуализировать шаблон для генерации HTTP-ответа.

И снова запрос будет отправлен обратно в промежуточное программное обеспечение, но уже ответа (response) для его обработки. Промежуточное программное обеспечение ответа обработает запрос и добавит или изменит информацию заголовка /информацию тела перед отправкой обратно клиенту (браузеру). После этого браузер обработает и отобразит его для конечного пользователя.

Промежуточное программное обеспечение - Middleware

Промежуточное программное обеспечение используется в ряде ключевых функций в проекте Django: например мы используем промежуточное ПО CSRF для предотвращения атак подделки межсайтовых запросов. Они используются для обработки данных сеанса. Аутентификация и авторизация осуществляется с использованием промежуточного программного обеспечения. Мы можем написать наши собственные классы промежуточного программного обеспечения для формирования (или замыкания) потока данных через ваше приложение.

process_request

Промежуточное ПО Django должно иметь хотя бы один из следующих методов: process_request, process_response, process_view и process_exception. Это методы, которые будут собраны обработчиком WSGI и затем вызваны в порядке их перечисления. Давайте кратко рассмотрим django.contrib.auth.middleware.AuthenticationMiddleware, одну из промежуточных программ, которые устанавливаются по умолчанию при запуске django-admin.py startproject:

def get_user(request):    if not hasattr(request, '_cached_user'):
        request._cached_user = auth.get_user(request)
    return request._cached_user


class AuthenticationMiddleware(MiddlewareMixin):    def process_request(self, request):
        assert hasattr(request, 'session'), (  "The Django authentication middleware requires session middleware"
  "to be installed. Edit your MIDDLEWARE%s setting to insert "
  "'django.contrib.sessions.middleware.SessionMiddleware' before "                    "'django.contrib.auth.middleware.AuthenticationMiddleware'."        ) % ("_CLASSES" if settings.MIDDLEWARE is None else "")
        request.user = SimpleLazyObject(lambda: get_user(request))

Как вы можете видеть, это промежуточное программное обеспечение работает только на этапе «запроса» потока данных, поступающего в приложение Django и из него. Это промежуточное программное обеспечение сначала проверяет, используется ли промежуточное программное обеспечение сеанса и уже было ли оно вызвано, затем устанавливает пользователя, вызывающего вспомогательную функцию get_user. Поскольку обработчик WSGI выполняет итерацию по списку методов process_request, он создает этот объект request, который в конечном итоге будет передан в представление, и вы сможете ссылаться на request.user. Некоторые из промежуточных программ в settings.py не будут иметь методы process_request. Ничего страшного; те просто пропускаются на этом этапе.

process_requests должен либо вернуть None (как в этом примере), либо альтернативно может вернуть объект HttpResponse. В первом случае обработчик WSGI продолжит обрабатывать методы process_request, а второй «закоротит» процесс и начнет цикл process_response.

Определение URL

Теперь, когда каждый из методов process_request был вызван, у нас теперь есть объект запроса, который будет передан представлению. Прежде чем это произойдет, Django должен разрешить URL и определить, какую функцию просмотра вызывать. Это просто делается путем сопоставления регулярных выражений. Ваш файл settings.py будет иметь ключ ROOT_URLCONF, который указывает на корневой файл urls.py, из которого вы будете включать файлы urls.py для каждого из ваших приложений. URL-маршрутизация довольно подробно описана в руководствах по Django, поэтому здесь нет необходимости углубляться в это.

Представление имеет три требования:

  1. Это должно быть вызваемым. Это может быть представление на основе функции или представление на основе класса, которое наследуется от метода as_view() класса View, чтобы сделать его вызываемым в зависимости от типа запроса HTTP (GET, POST и т.д.)
  2. Оно должно принимать объект HttpRequest в качестве первого позиционного аргумента. Это результат вызова всех методов process_request и process_view.
  3. Оно должно возвращать объект HttpResponse или вызывать исключение. Именно этот объект ответа используется для запуска цикла process_view обработчика WSGI.

process_view

Теперь, когда обработчик WSGI знает, какую функцию представления вызывать, он снова просматривает свой список методов промежуточного программного обеспечения. Метод process_view для любого промежуточного программного обеспечения Django объявлен так:

process_view(request, view_function, view_args, view_kwargs)

Как и в случае с process_request, функция process_view должна возвращать либо None, либо объект HttpResponse (или вызывать исключение), что позволяет обработчику WSGI либо продолжать обработку представлений, либо «закорачивать» и возвращать ответ. Взгляните на исходный код промежуточного программного обеспечения CSRF, чтобы увидеть пример process_view в действии. Если файл cookie CSRF присутствует, метод process_view возвращает None, и выполняется представление. Если нет, запрос отклоняется, и процесс замыкается, что приводит к сообщению об ошибке.

process_exception

Если функция представления вызывает исключение, обработчик перебирает свой список методов process_exception. Эти методы выполняются в обратном порядке, от последнего промежуточного программного обеспечения, указанного в файле settings.py, до первого. Если возникает исключение, процесс будет закорочен, и никакие другие process_exception не будут вызваны. Обычно мы полагаемся на обработчики исключений, предоставляемые Django BaseHandler, но вы, безусловно, можете реализовать свою собственную обработку исключений, когда пишете свой собственный класс промежуточного ПО.

process_response

На этом этапе у нас будет объект HttpResponse, возвращаемый представлением или списком методов process_view, созданных обработчиком WSGI, и пришло время поочередно циклически проходить через промежуточное ПО ответа. Это последний шанс для любого промежуточного программного обеспечения изменить данные, и они выполняются из внутреннего слоя наружу. Взгляните на исходный код промежуточного программного обеспечения кеша, чтобы увидеть пример действия process_response: в зависимости от различных условий в вашем приложении (например, отключено ли кэширование, имеем ли мы дело с потоком и т.д.), Нам понадобится ответ хранится в кеше или нет.

Примечание: Есть одно отличие между Django до 1.10 и более поздними версиями: в старом MIDDLEWARE_CLASSES у каждого промежуточного программного обеспечения всегда будет вызываться метод process_response, даже если более раннее промежуточное программное обеспечение закорачивало процесс. В новом MIDDLEWARES только те промежуточные программы и те, которые выполнялись до этого, будут вызывать свои методы process_response. Обратитесь к документации для получения более подробной информации о различиях между MIDDLEWARES и MIDDLEWARE_CLASSES.

Все сделано!

Наконец, обработчик Django WSGI создает возвращаемое значение из объекта HttpResponse и выполняет функцию обратного вызова для отправки этих данных на веб-сервер и для пользователя.

Итак, два ключевых вывода:

  1. Теперь мы знаем, как функция представления сопоставляется с URLconf и что на самом деле вызывается (обработчик WSGI).
  2. Существует четыре ключевых момента, которые вы можете подключить к циклу запрос/ответ через свое собственное промежуточное ПО: process_request, process_response, process_view и process_exception.

Перевод статьи https://medium.com/@ksarthak4ever/django-request-response-cycle-2626e9e8606e

Вернуться на верх