Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

middleware vs. context processor for view dependent navigation/display

Tags:

django

This is a very similar question to this SO thread on middleware and views communicating

We'd like to have our templates be given a standard set of context variables. So, a context processor seems appropriate, however, it doesn't seem like the context processor is view-aware. We'd previously been forced to inspect the call stack to get contextual information on what view was doing what.

That's where we saw the middleware thread as well as the process_view() signature for a middleware that gives us a handle to the view.

This seemed closer to our needs, but didn't allow us to modify the context variable, neither did the other middleware methods.

So our intial idea bandied about was to modify the request object with all the global and contextual information we needed for our templates and force the templates to call from the {{request.something}} for the specific information we need, such as {{request.viewname}}.

So, our questions:

  • Is modifying/setting values on the request object an accepted thing to do for pushing contextual/global app specific information to your templates? Or is the standard practice always to put it into contexts?
  • Are there ways/tricks to make context processors view aware that don't involve passing it explicitly or doing some stack introspection?
  • Does the middleware.process_response have an opportunity to modify the context or is it immutable?
like image 568
dmyung Avatar asked Aug 14 '09 16:08

dmyung


2 Answers

It's perfectly valid to set variables on the request in middleware - I do it all the time.

There's no way to use process_response for this, as by then the template has already been rendered - at this point all you get is an HttpResponse containing a bunch of HTML.

An alternative might be to wrap render_to_response with your own function, which takes the context, together with the request and template, and modifies it as necessary before handing off to the actual render function. This has the advantage of modifying the actual context, but the disadvantage that you have to actually remember to call it in every view instead of the default function.

like image 194
Daniel Roseman Avatar answered Nov 02 '22 12:11

Daniel Roseman


You could do it by using middleware and a context processor in tandem. The middleware knows about the view, and can set an attribute on the request. Then the context processor can move anything set on the request into the context.

For example:

class ExtraContextMiddleware(object):
    """
    Adds extra context to the response for certain views.

    Works in tandem with the extra_context context processor.
    """

    context_map = {
        #Adds the supplied context dict to the named views
        'my_view_name': {'foo': 'Hello', 'bar': 'Goodbye'},
    }

    def process_view(self, request, view, *args, **kwargs):
        try:
            request.extra_context = self.context_map[view.func_name]
        except KeyError:
            pass

Then the context processor:

def extra_context(request):
    """Context processor for adding extra context.
    Works in tandem with ExtraContextMiddleware."""
    try:
        return request.extra_context
    except AttributeError:
        return {}
like image 31
seddonym Avatar answered Nov 02 '22 13:11

seddonym