django custom templatetag not getting request in context

孤街醉人 提交于 2019-12-23 16:43:02

问题


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'

回答1:


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.




回答2:


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})



回答3:


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




回答4:


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.



来源:https://stackoverflow.com/questions/10288868/django-custom-templatetag-not-getting-request-in-context

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!