Почему 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
, которому необходимо обеспечить отображение ответа, поскольку он оборачивает как первое, так и последнее промежуточное ПО в цепочке.
Похоже, вы используете промежуточное ПО для добавления значений в контекст, что не самое лучшее место для этого. Вместо этого вам следует написать пользовательский обработчик контекста, который будет вызываться последовательно.