I'm trying to create a custom tag. Inside this custom tag, I want to be able to have some logic that checks if the user is logged in, and then have the tag rendered accordingly. This is what I have:
def user_actions(context):
request = template.Variable('request').resolve(context)
return { 'auth': request['user'].is_athenticated() }
register.inclusion_tag('layout_elements/user_actions.html', takes_context=True)(user_actions)
When I run this, I get this error:
Caught VariableDoesNotExist while rendering: Failed lookup for key [request] in u'[{}]'
The view that renders this ends like this:
return render_to_response('start/home.html', {}, context_instance=RequestContext(request))
Why doesn't the tag get a RequestContext object instead of the Context object? How can I get the tag to receive the RequestContext instead of the Context?
EDIT:
Whether or not it's possible to get a RequestContext inside a custom tag, I'd still be interested to know the "correct" or best way to determine a user's authenticati开发者_开发问答on state from within the custom tag. If that's not possible, then perhaps that kind of logic belongs elsewhere? Where?
By default, an instance of django.template.Context
is used in rendering templates, but you can override this in your view, either by passing a subclass of django.template.Context
as the context_instance
keyword argument to render_to_response
, or by instantiating the subclass, and passing it directly to Template.render
.
For convenience, Django provides a useful, pre-defined Context
subclass: django.template.RequestContext
. RequestContext
looks in your settings file for a setting called TEMPLATE_CONTEXT_PROCESSORS
, which should be a tuple of callable objects, each of which should return a dictionary; RequestContext
will loop over each callable, call it, and add the key/value pairs from its returned dictionary to the template context as variables. Check out these links for a more detailed explanation.
To add the current user to your template context, you need django.core.context_processors.auth
:
Add the
django.core.context_processors.auth
context processor to your list of context processors insettings.py
:TEMPLATE_CONTEXT_PROCESSORS = ( 'django.core.context_processors.auth', ... # Other context processors follow )
Ensure the view than renders the template which calls your custom tag uses
RequestContext
:from django.template.context import RequestContext from django.shortcuts import render_to_response def my_view(request): # Do some stuff return render_to_response('templates/view.html', context_instance=RequestContext(request))
Using
RequestContext
calls all context processors defined insettings.TEMPLATE_CONTEXT_PROCESSORS
, including theauth
context processor, which adds a context variable 'user' to your template context.
In your template tag, you can access this variable viacontext['user']
@register.inclusion_tag('templates/custom/tag.html', takes_context=True) def custom_tag(context): user = context['user'] if user.is_authenticated(): # Some stuff for the logged-in users else: # Stuff for anonymous users
i dont see how your view is linked to the template tag, because from what i know its django's template system that renders the tag, so the context is a dictionary, try this, hopefully it helps
user = context['user']
if user.is_authenticated():
do stuff
The "context" of a template node is a different thing to the RequestContext
. A Context
is also a dictionary, so if it has a user at all it would be accessed via context['user']
.
The template nodes context contains information to help it render itself within the template, after doing some reading of the docs, I cannot find any way to access the RequestContext
which would be associated with the request via the django.template.Context
.
Moreover django.template.RequestContext
extends from django.template.Context
specifically in order to handle the added request object which would contain the user. So it is no surprise that Context
would not have access to it.
See the source code of Context
for proof.
How to get the user
After a bit of searching I found the django.template.resolve_variable
method which can be used as follows:
from django.template import resolve_variable
user = resolve_variable('user', context)
Where context
is a template context.
I ended up just passing the "user" parameter to the tag and using that to decide if the user was auth'd or not.
精彩评论