【问题标题】:django custom templatetag not getting request in contextdjango 自定义模板标签未在上下文中获取请求
【发布时间】:2012-05-04 13:20:35
【问题描述】:

我正在使用 django 1.4 并尝试将this article 末尾描述的代码转换为自定义标签。这意味着我需要访问请求中的 is_secure 和 site_name 值。这是我在 settings.py 中的 CONTEXT_PROCESSORS:

CONTEXT_PROCESSORS = (
    'django.core.context_processors.request',
    'django.contrib.auth.context_processors.auth',
)

这是我的模板标签代码:

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

在我的视图代码中,我正在使用新的渲染快捷方式,如下所示:

return render(request, 'myapp/mytemplate.html', {'foo':bar})

我在模板中这样称呼它:

{% full_static_url "images/logo.gif" %}

问题是,当它到达 request = context['request'] 行时,它会抛出 KeyError,因为 'request' 不在上下文中。

我在这里做错了什么?

完整的追溯是:

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'

【问题讨论】:

  • @CppLearner 我试过了,但我怀疑,同样的问题。尝试从上下文映射中获取请求时出现 KeyError。
  • 就像完整性检查一样,您的 settings.py 中是否真的有 CONTEXT_PROCESSORS 或更好的变体 TEMPLATE_CONTEXT_PROCESSORS ?
  • 对不起,我不得不跳到其他任务上,现在才回到这个问题。 @loomi 我真的在使用 CONTEXT_PROCESSORS,我不知道 TEMPLATE_CONTEXT_PROCESSORS。不过我会试一试,然后告诉你。
  • 您找到解决方案了吗?我现在遇到完全相同的问题。在我的代码中一切看起来都正确,但是请求对象没有被传递。

标签: django django-templates


【解决方案1】:

问题很可能是您使用常规上下文渲染模板,就像这样:

return render_to_response("myapp/template.html", {"some_var": a_value})

请记住,上下文处理器仅适用于 RequestContext 实例。这意味着您必须在 render_to_response 调用中显式创建 RequestContext

return render_to_response("myapp/template.html", {"some_var": a_value},
                          context_instance=RequestContext(request))

或者更好的是,使用新的render 快捷方式:

return render(request, "myapp/template.html", {"some_var": a_value})

【讨论】:

  • 其实我用的是渲染快捷方式。我应该在我的描述中提到这一点。我现在添加它。
  • 以防万一,我尝试了 render_to_response 方法(使用 RequestContext)同样的问题。
  • 好吧,在这种情况下,代码看起来是正确的,你能粘贴你得到的确切回溯吗?
  • 将堆栈跟踪添加到上述问题
  • 好的,我想到了两件事:1)尝试在您的视图中创建一个RequestContext 实例并记录(打印或其他)它的dicts 属性以查看它是否包含request物品。 2) 尝试从模板标签中记录context.dicts 以检查它是否获得了正确的上下文实例。
【解决方案2】:

我通过改变解决了它

return render(request, 'myapp/mytemplate.html', {'foo':bar})

return render( RequestContext(request), 'myapp/mytemplate.html', {'foo':bar})

我希望这对其他人有帮助,我浪费了大约 8 个小时 :p

【讨论】:

  • 第二个代码是错误的,render 已经这样做了。您可能在TEMPLATE_CONTEXT_PROCESSORS 中缺少django.core.context_processors.request
  • 这可行,但恕我直言,这不是最好的解决方案。我认为锂的添加到 TEMPLATE_CONTEXT_PROCESSORS 的解决方案是一个更好的解决方案。
【解决方案3】:

我在 render() 中的 template.Node 对象中发生了这种情况。事实证明,有时上下文中包含“请求”,有时则没有。

就像其他人建议的那样,RequestContext(request) 是关键。我的猜测是,有时会在没有像这样初始化请求的情况下调用上下文。

我改变了我的功能

 def render(self, context):
      request = context['request']  # Failing here

 def render(self, context):
      request = RequestContext(context)['request']['request']

一切顺利。

如果上下文对象未正确初始化,这将强制请求对象。出于某种原因,我不得不添加 ['request'] 两次,但它似乎工作正常


编辑:我说得太早了,似乎无法修复空白上下文。相反,您可以尝试一种解决方法:

request = context.get('request')
if request is None:
    return ''

我的页面似乎仍然可以正常工作,所以我不确定这些不良上下文是从哪里来的。

【讨论】:

    【解决方案4】:

    解决此问题的正确方法是在您的 settings.py 文件中添加 TEMPLATE_CONTEXT_PROCESSORS += ("django.core.context_processors.request",)

    确保先用from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS导入TEMPLATE_CONTEXT_PROCESSORS,否则不起作用。

    【讨论】:

    • 这是我在 estecb 对上述 Pheonix 的回答发表评论后最终做的事情。你是第一个真正写下这个作为答案的人。谢谢!
    • 在更新的 Django 版本中,TEMPLATE_CONTEXT_PROCESSORS 已被弃用,并已替换为 TEMPLATES['OPTIONS']['context_processors']。在这种情况下,你会导入什么?
    猜你喜欢
    • 2019-02-07
    • 2011-01-10
    • 2015-01-20
    • 1970-01-01
    • 2016-02-25
    • 2017-07-29
    • 2021-07-13
    • 2013-03-30
    相关资源
    最近更新 更多