17Sep

Django: How to ensure the function name and context name are the same for context processing

Posted by Elf Sternberg as django, python

We frequently write little functions that populate the Django context, and sometimes we want that context to be site-wide, and we want every page and every Ajax handler, basically everything that takes a request and spews a response, in our application to have access to that information.  It might the user’s authentication, or his authorization, or some profile information.  Or it might be environmental: a site might have figured out what time it is on the user’s site, and will adjust backgrounds and themes accordingly.

The context might be a simple variable.  I have an example right here: is the browser you’re using good enough?  (I know, this is considered Bad Form, but it’s what I have to work with) .  The function has the simple name, need_browser_warning.  The context key may as well have the same name.  Using a constant for the context key is the usual pattern; this ensures the Django programmer won’t get it wrong more than once, at least on the view side.  (The template is another issue entirely.  Set your TEMPLATE_STRING_IF_INVALID in settings.py!)

I wanted something more clever in my context processor.  Here’s sickly clever:

import inspect
def need_browser_warning(request):
    return { inspect.currentframe().f_code.co_name:
        not adequate_browser(request.META.get('HTTP_USER_AGENT')) }

Yeah, that’s a little twisted.  It guarantees that the name of the context key is “need_browser_warning“, and the value is True or False depending upon what the function “adequate_browser” returns, which is what we want, so it’s all good.

Obviously, this isn’t good for everything.  Some context processors handle many, many values.  But for a one-key, this is a nifty way of ensuring name consistency.

3 Responses to Django: How to ensure the function name and context name are the same for context processing

Leo Shklovskii

September 17th, 2009 at 1:43 pm

This is a nifty idea, but you can do it in a slightly less sickly clever way if you were to put it in a decorator, for example:

def same_name_in_context(fn):
def new_func(*args):
return { fn.func_name : fn(*args) }
return new_func

@same_name_in_context
def need_browser_warning(request):
return not adequate_browser(request.META.get(‘HTTP_USER_AGENT’))

Leo Shklovskii

September 17th, 2009 at 1:43 pm

ugh, and the comment form killed all of my spacing… should still be pretty clear :-/

Elf Sternberg

September 17th, 2009 at 2:21 pm

That’s true, but oddly enough, it’s actually less performant. I ran the numbers, and the inspect method is twice as efficient under cProfile. Not that that’s a good excuse for obfuscation, but it’s a point in inspect’s favor.

Comment Form

Subscribe to Feed

Categories

Calendar

September 2009
M T W T F S S
« Aug   Oct »
 123456
78910111213
14151617181920
21222324252627
282930