views:

3656

answers:

5

I am writing a custom tag in Django that should output a value stored in a user session, but I cannot find a way to access the session object from within a custom tag function. Is there any way to do this, without manually assigning the session object to a context variable?

+1  A: 

You can do this with custom context processors (see http://docs.djangoproject.com/en/dev/ref/templates/api/)

In this case, you'd create a new file called context_processors.py at the same level as your settings.py file, containing:

def add_session(request):
    return {'session': request.session}

Then, in your settings.py file, add:

TEMPLATE_CONTEXT_PROCESSORS = ("django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
'context_processors.add_session',)

You'll now be able to refer to context['session'] in your custom tag.

Note that this will only work for templates rendered with a RequestContext assigned, as in the following code:

def test(request):
    return render_to_response('test.html',{}, context_instance=RequestContext(request))
Matthew Christensen
+9  A: 

You should be able to add the request context processor in your settings.py file:

TEMPLATE_CONTEXT_PROCESSORS = ("django.core.context_processors.auth", "django.core.context_processors.debug", "django.core.context_processors.i18n", "django.core.context_processors.media", 'django.core.context_processors.request',)

This will do the same thing as the current answer, without having to add a custom file.

Michael Warkentin
I'd recommend switching answer to this approach, it's cleaner.
Matthew Christensen
I already had that preprocessor, but must have overlooked the session property. D'oh! Thanks.
knabar
I have added this, but how do I access the request from within the template? context.session does not exist.
Wouter
@Wouter the session is available at `request.session`
TM
A: 

I found this useful: http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser

You can use middleware to grab the user info and store it with a local thread, and then use it with your tag definition.

A: 

No offense intended Sebastian as that seems like it was a useful hack at one point, but oddly enough on December 24 in a blog entry about accessing User data in the Admin, James Bennett, Django's release manager, had this to say about using the threadlocal hack:

A big fat disclaimer: there are lots and lots of potential uses for these types of features. Many of them are wrong and stupid and you shouldn’t be trying them. ... Also, you will occasionally see someone suggest that these features can be obtained by what’s known as the "threadlocal hack"; this basically involves sticking request.user into a sort of magical globally-available variable, and is a Very Bad Thing to use if you don’t know what you’re doing. It’s also generally a Very Bad Thing to use even if you do know what you’re doing, since you’re probably just doing it because you’re lazy and don’t feel like ensuring you pass information around properly. So if you see someone suggesting that you do this using a "threadlocal", ignore that person.

Not saying that you should ignore Sebastian, but it might be worthwhile pursuing other avenues rather than using threadlocal which is not considered a best practice.

A: 

Using render_to decorator from django-annoying seems to be the best option (as seen in another question on stackoverflow)

tpk