Reputation: 1360
I am using django 1.4 and trying to convert the code described at the end of this article into a customtag. This means I need access to the is_secure and site_name values from the request. Here is my CONTEXT_PROCESSORS in settings.py:
CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
'django.contrib.auth.context_processors.auth',
)
Here is my template tag code:
from django import template
register = template.Library()
@register.simple_tag(takes_context=True)
def full_static_url(context, url):
request = context['request']
scheme = 'http'
if request.is_secure:
scheme += 's'
return scheme + '://' + request.site_name + context['STATIC_URL'] + url
In my view code I am using the new render shortcut like so:
return render(request, 'myapp/mytemplate.html', {'foo':bar})
And I am calling it like this in the template:
{% full_static_url "images/logo.gif" %}
The problem is, when it gets to the line request = context['request'] it throws a KeyError because 'request' is not in context.
What am I doing wrong here?
Full traceback is:
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "C:\Projects\blah\blah\myapp\views\myview.py" in manifestcosts
44. return render(request, 'myapp/mytemplate.html', {'foo':bar})
File "C:\Python27\lib\site-packages\django\shortcuts\__init__.py" in render
44. return HttpResponse(loader.render_to_string(*args, **kwargs),
File "C:\Python27\lib\site-packages\django\template\loader.py" in render_to_string
176. return t.render(context_instance)
File "C:\Python27\lib\site-packages\django\template\base.py" in render
140. return self._render(context)
File "C:\Python27\lib\site-packages\django\template\base.py" in _render
134. return self.nodelist.render(context)
File "C:\Python27\lib\site-packages\django\template\base.py" in render
823. bit = self.render_node(node, context)
File "C:\Python27\lib\site-packages\django\template\debug.py" in render_node
74. return node.render(context)
File "C:\Python27\lib\site-packages\django\template\defaulttags.py" in render
185. nodelist.append(node.render(context))
File "C:\Python27\lib\site-packages\django\template\base.py" in render
1107. return func(*resolved_args, **resolved_kwargs)
File "C:\Projects\blah\blah\myapp\templatetags\mytags.py" in full_static_url
25. request = context['request'] #TODO this fails with an KeyError, don't know why
File "C:\Python27\lib\site-packages\django\template\context.py" in __getitem__
54. raise KeyError(key)
Exception Type: KeyError at /myapp/myurl/110505081136179000/
Exception Value: 'request'
Upvotes: 3
Views: 7781
Reputation: 647
The right way to fix this issue is to add TEMPLATE_CONTEXT_PROCESSORS += ("django.core.context_processors.request",)
on your settings.py file.
Ensure to import TEMPLATE_CONTEXT_PROCESSORS
first with from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
or it will not work.
Upvotes: 10
Reputation: 3
I had this happen in a template.Node object in the render(). It turned out that sometimes the context had 'request' in it, other times it didn't.
Like someone else suggested, RequestContext(request)
is the key. My guess is that sometimes the context is called without the request being initialized like that.
I changed my function from
def render(self, context):
request = context['request'] # Failing here
to
def render(self, context):
request = RequestContext(context)['request']['request']
and it all came right.
This will force a request object in case the context object wasn't initialized properly. For some reason I had to add ['request'] twice, but it seems to work fine
EDIT: I spoke too soon, seems a blank context can't be fixed. Instead you could try a workaround:
request = context.get('request')
if request is None:
return ''
My page still seems to work fine, so I'm not exactly sure where these bad contexts are coming from.
Upvotes: 0
Reputation: 6052
I solved it by changing
return render(request, 'myapp/mytemplate.html', {'foo':bar})
to
return render( RequestContext(request), 'myapp/mytemplate.html', {'foo':bar})
I hope this helps someone else, I wasted about 8 hours :p
Upvotes: 0
Reputation: 4382
Most likely the problem is you are rendering your template using regular context, that is something like this:
return render_to_response("myapp/template.html", {"some_var": a_value})
Remember that context processors are only applied to RequestContext
instances. That means you have to either explicitly create a RequestContext
in your render_to_response
call:
return render_to_response("myapp/template.html", {"some_var": a_value},
context_instance=RequestContext(request))
or even better, use the new render
shortcut:
return render(request, "myapp/template.html", {"some_var": a_value})
Upvotes: 1