Почему Middleware не обрабатывается на странице 404 в Django?

Итак, я установил путь в моей конфигурации URL:

path(
    "kitten/",
    views.Kitten.as_view(),
    name="kitten",
),

и обработчик для отсутствующих URL к тому же представлению.

handler404 = views.Kitten.as_view()

У меня есть некоторое промежуточное ПО, которое устанавливает некоторые контекстные данные:

class CookieConsentMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        return self.get_response(request)

    def process_template_response(self, request, response):
        response.context_data["hasCookie"] = False        
        return response

и вид очень простой,

class Kitten(TemplateView):
    template_name = "kitten.html"

и шаблон печатает значение hasCookie.

При посещении kitten/ правильно отображается значение hasCookie, но при посещении URL, который не существует, не отображается значение hasCookie (при этом показывается правильный шаблон)

Добавив отладочные утверждения в промежуточное ПО, становится очевидно, что в то время как process_view, process_template_response и process_exception вызываются для kitten/, ни один из них не вызывается для несуществующих URL, поэтому не вызывается код для установки значения hasCookie. (__init__ вызывается независимо при запуске приложения)

Почему он не вызывает промежуточное ПО, когда URL не найден в URLconf?

Your middleware does get called but not its process_template_response method since Django calls the render function on the response from the exception handler making it not a TemplateResponse object anymore. This can be seen in the code [GitHub] for the response_for_exception function:

# Force a TemplateResponse to be rendered.
if not getattr(response, "is_rendered", True) and callable(
    getattr(response, "render", None)
):
    response = response.render()

Это происходит потому, что response_for_exception вызывается convert_exception_to_response, которому необходимо обеспечить отображение ответа, поскольку он оборачивает как первое, так и последнее промежуточное ПО в цепочке.

Похоже, вы используете промежуточное ПО для добавления значений в контекст, что не самое лучшее место для этого. Вместо этого вам следует написать пользовательский обработчик контекста, который будет вызываться последовательно.

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