Что такое Middleware в Django и какие примеры можно привести?

Ответ

Middleware (промежуточное ПО) в Django — это система "хуков" в цикле обработки запроса/ответа. Это компоненты, которые обрабатывают запрос перед тем, как он достигнет view, и ответ после того, как он будет сгенерирован view. Их можно представить как слои луковицы, через которые проходит каждый запрос и ответ.

Основные встроенные Middleware

Django поставляется с набором стандартных Middleware, которые включены в проект по умолчанию:

  1. django.middleware.security.SecurityMiddleware Обеспечивает несколько важных улучшений безопасности: управляет заголовками X-Content-Type-Options, X-XSS-Protection, Strict-Transport-Security (HSTS) и другими.

  2. django.contrib.sessions.middleware.SessionMiddleware Включает поддержку сессий, позволяя хранить данные между запросами для каждого пользователя.

  3. django.middleware.csrf.CsrfViewMiddleware Добавляет защиту от атак типа "Межсайтовая подделка запроса" (CSRF) путем проверки специального токена в POST-запросах.

  4. django.contrib.auth.middleware.AuthenticationMiddleware Добавляет объект user (request.user) к каждому входящему объекту HttpRequest, представляя текущего залогиненного пользователя.

Пример кастомного Middleware

Вы можете легко создавать свои Middleware для решения специфичных задач, например, для логирования времени выполнения запроса.

# myapp/middleware.py
import time

class TimingMiddleware:
    def __init__(self, get_response):
        # Выполняется один раз при инициализации сервера
        self.get_response = get_response

    def __call__(self, request):
        # Код, который выполняется перед вызовом view
        start_time = time.time()

        response = self.get_response(request)

        # Код, который выполняется после вызова view
        duration = time.time() - start_time
        print(f"View executed in {duration:.2f}s")

        return response

Регистрация в settings.py

Чтобы Middleware заработало, его нужно добавить в список MIDDLEWARE:

# settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    # ... другие middleware
    'myapp.middleware.TimingMiddleware', # Наш Middleware
    # ...
]

Важно: Порядок Middleware имеет значение. При обработке запроса они выполняются сверху вниз, а при обработке ответа — в обратном порядке, снизу вверх.

Ответ 18+ 🔞

Так, слушай, а вот эта ваша "луковица" в Django, эта middleware, блядь... Это ж просто пиздец какая удобная штука, если разобраться, а не тупить как Герасим из "Муму", который нихуя не понимал, что творит.

Представь себе, что каждый запрос к твоему сайту — это такой вот Герасим, здоровый, немой, идёт он через лес. А middleware — это, блядь, как раз те самые слои, через которые он пробирается. Сначала на него SecurityMiddleware накидывается — типа "стой, мужик, а ты не опасный? Хули ты без шлема идёшь, токены CSRF у тебя есть?". Потом SessionMiddleware его по голове гладит: "А, это ты, Вася? Я тебя помню, в прошлый раз ты корзину не оплатил, сука". И так далее, пока он, бедолага, до вьюхи не доползёт.

А самое офигенное, что ты можешь своего Герасима, то есть запрос, по пути чем-нибудь обвешать. Хочешь засечь, сколько он идёт? Заебись! Напиши свой промежуточный слой, который будет засекать время. Смотри, как просто, ёпта:

# myapp/middleware.py
import time

class TimingMiddleware:
    def __init__(self, get_response):
        # Это как будто ты Герасиму сказал: "Стой тут, я за тобой следить буду".
        # Выполняется один раз при старте сервера.
        self.get_response = get_response

    def __call__(self, request):
        # А вот тут Герасим (запрос) уже реально пошёл.
        # Засекаем время, блядь, старт!
        start_time = time.time()

        # Пускаем его дальше по цепочке middleware, пока он до вьюхи не дойдёт.
        response = self.get_response(request)

        # О, он вернулся с ответом! Смотрим, сколько времени он там проёбывался.
        duration = time.time() - start_time
        # И выводим в консоль, для полного охуения.
        print(f"View executed in {duration:.2f}s")

        return response

Ну и чтобы этот наш хронометрист заработал, его, как и любого нормального сторожа, надо на работу устроить. Идёшь в settings.py и вписываешь в список MIDDLEWARE:

# settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    # ... другие стандартные охранники...
    'myapp.middleware.TimingMiddleware', # А вот и наш мудила с секундомером!
    # ...
]

И вот тут, внимание, ебаный в рот момент! Порядок имеет значение, как в очереди за водкой! Когда запрос идёт внутрь, эти прослойки срабатывают сверху вниз. А когда ответ вылезает наружу — они, сука, работают в обратном порядке, снизу вверх! Так что если твой TimingMiddleware будет в конце списка, он засечёт ВСЁ время, включая работу других middleware. А если поставишь его в начало — он засечёт только время после себя. Вот такая, блядь, матрёшка получается, в рот меня чих-пых!

Короче, middleware — это мощнейший инструмент, чтобы накрутить на свой проект любую логику, которая должна выполняться для КАЖДОГО запроса. Логирование, проверка прав, добавление заголовков, геолокация по IP — да что угодно, лишь бы фантазии хватило и не накосячить с порядком, как тот самый Герасим, который сначала собаку утопил, а потом совесть его ебать начала.