Использование middleware в Django

lepiloff

Jan. 18, 2018, 2:10 p.m.

Говоря простым языком, middleware - это промежуточный слой между запросом(request) и ответом (response). В фреймворке Django уже по умолчанию содержатся наиболее важные и нужные middleware. Каждый компонент промежуточного слоя отвечает за определенный функционал. Например, Django предоставляет компонент AuthenticationMiddleware, который ассоциирует пользователей с запросами с помощью сессий. Список предустановленных промежуточных слоев можно посмотреть в файле настроек. Узнать о них подробней можно в официальной документации.

settings.py

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

В процессе выполнения запроса request все middleware выполняются сверху вниз. Это значит, что сначала выполняется SecurityMiddleware, затем SessionMiddleware и т.д. На этом этапе для каждого из слоев выполняются два метода process_request() и process_view(). На этом этапе Django выполнит всю работу над вашей функцией в пердставлении views.py. Когда обработка функции закончена (получены queryset-ы, сформирована пагинация и т.д.) клиенту возвращается ответ response. 

Response возвращается в обратном порядке - снизу в верх и для каждого слоя выполняются методы process_exception(), process_template_response() и process_response().

Более наглядно увидить мезанизм работы промежуточных слоев можно на картинке.

Создание собственных middleware

Допустим нам необходимо вывысти список категорий товаров. Это можно сделать передав qweryset в представление функции вывода html шаблона, содержащего перечень категорий. Но если нам нужно получать его на каждой странице сайта, например в основном меню сайта, то это проще сделать передачей в base.html. Но ведь base.html не выводиться никаим представлением, в этом и сложность. Вот тут то и приходит на помощь middleware. Для создания собственного промежуточного слоя, необходимо создать новый клас и сохранить его в файле, который надо добавить в settings.py в разделе MIDDLEWARE. Назовем этот файл middleware.py, а класс -  GetCategory и сохраним в приложении myapp.

middleware.py

from django.utils.deprecation import MiddlewareMixin
from printer.models import ProductType

class GetCategory(MiddlewareMixin):
    def process_request(self, request):

        category_list= ProductType.objects.all()
        request.category_list = category_list
        return None

Добавим новый промежуточный слой в файл настроек пректа.

settings.py

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    ...
    ...
    'myapp.middleware.GetCategory',
]

Для доступа к из шаблона необходимо необходимо обращаться через request

html

{% for obj in request.category_list %}
{{ obj.type}}
{% endfor %}

django