Opened 8 years ago

Closed 8 years ago

#27011 closed Bug (invalid)

Django Middleware 1.10 does not run template_context_processors for exceptions thrown from middleware

Reported by: Kyle Agronick Owned by: nobody
Component: HTTP handling Version: 1.10
Severity: Normal Keywords: django middleware 1.10
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

If an exception in thrown such as django.core.exceptions.PermissionDenied from the new style middleware the resulting template will not have any of the variables provided from template context_processors. This creates broken pages missing all of the variables expected to be present in a site's base templates. That means no request variable is set from django.template.context_processors.request. No Javascript or CSS can render because STATIC_URL is not set. Only the variables set in the error handler will be available.

Since it is a common use case to check for permissions in middleware, or to check if objects exist, the error pages it creates shouldn't be half baked. This is the only place I can find in Django where templates missing these variables will be rendered. This does not appear to be normal anywhere else.

Also, with debug mode on the error pages it renders are not the debug error pages, but the ones found when debug mode is turned off.

The only way I can find around this is to fill in all the missing variables in a custom error handler. This requires reproducing everything context_processors does to make a working page.

Change History (4)

comment:1 by Carl Meyer, 8 years ago

Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

comment:2 by Tim Graham, 8 years ago

I'm not about to replicate this behavior in my own tests. Could you provide a sample project that reproduces this?

I created a custom 403.html template that includes {{ STATIC_URL }} and appended a middleware that looks like this to settings.MIDDLEWARE:

from django.core.exceptions import PermissionDenied
from django.utils.deprecation import MiddlewareMixin

class Middleware(MiddlewareMixin):
    def process_request(self, request):
        raise PermissionDenied

I see the STATIC_URL on the rendered page.

comment:3 by Kyle Agronick, 8 years ago

I made a demo project that shows the issue. All you need to do is clone it and you can run ./manage.py runserver. There is a variable in settings.py called THROW_EXCEPTION. When it is turned on you'll see no variables except the ones provided in the error handler. When its turned off all the template context processor variables will be available.

Here is the repo:
https://github.com/agronick/django_middleware_error

comment:4 by Tim Graham, 8 years ago

Resolution: invalid
Severity: Release blockerNormal
Status: newclosed
Type: UncategorizedBug

This looks like a usage mistake. Your custom error handler uses render_to_response(), however, as described in the documentation, "If you need to use context processors, render the template with a RequestContext instance instead." More simply, you can use django.shortcuts.render() instead.

I see the context processor values in the error template after modifying error_handlers.py like this:

from django.shortcuts import render
...
        resp = render(request, self.get_template_name(), context, status=self.status_code)
Note: See TracTickets for help on using tickets.
Back to Top