【问题标题】:Django custom context processor being called twice per request每个请求调用两次 Django 自定义上下文处理器
【发布时间】:2009-09-19 03:54:32
【问题描述】:

我创建了一个只需要运行的简单自定义上下文处理器 每个请求一次。在放入一些日志钩子后,我发现它 每个请求被调用两次。

这是文档中遗漏的已知“功能”吗? 是不是跟继承树中的模板个数有关? 是不是 1.03 的 bug?

【问题讨论】:

  • 我对此进行了进一步研究,似乎每个上下文处理器在模板继承树中的每个模板都执行一次。我有两个模板 - base.html 和 homepage.html。这似乎真的很低效,我有点惊讶它会发生。我希望这只是我的一个愚蠢的疏忽。
  • 对我来说似乎没问题。你有两个模板,都需要适当的上下文。这听起来像 struts 中的拦截器堆栈。
  • 您使用了哪些日志记录挂钩?有时,如果您使用 Python 的日志记录包并无意中添加了多个处理程序,您会得到两次消息输出。检查这些事件的时间戳。
  • 也许这对某人有帮助。使用 django-debug-toolbar 中间件时会发生这种情况。

标签: django preprocessor django-context


【解决方案1】:

这不是预期的行为。上下文处理器执行一次each time a RequestContext is instantiated)。在模板继承的情况下,the same context instance is passed up to the parent template,因此不应导致上下文处理器的另一个执行。您的日志记录具有误导性(请参阅@Vinay Sajip 的评论),或者您需要弄清楚代码中的哪个位置可能会在每个请求上执行额外的 RequestContext(您是使用包含标签还是其他呈现模板的自定义模板标签和实例化 RequestContext?)

编辑抱歉,“包含标签”是指(在一般意义上)呈现另一个模板的某个标签,而不是任何使用包含标签装饰器的标签。接受上下文的常规包含标签应该简单地传递现有的上下文对象,而不是实例化新的 RequestContext。

您可以尝试的一件事是在您的上下文处理器中放置一个“import pdb;pdb.set_trace()”,在 Django 开发服务器中运行代码,然后在控制台中每次使用 pdb 检查您的上下文时的堆栈跟踪处理器被击中,看看它是从哪里被调用的。

【讨论】:

  • 我正在使用一个自定义包含标签,该标签将“上下文”作为参数。鉴于这是预期的行为?我没有意识到包含标签会导致上下文处理器再次运行。
【解决方案2】:

在我的情况下,当使用 django debug_toolbar 时会出现此错误。为避免这种情况,请尝试发表评论

debug_toolbar.middleware.DebugToolbarMiddleware

【讨论】:

【解决方案3】:

我发现了这个问题。如果返回原始上下文以外的字典,则似乎再次执行上下文处理器。不知道为什么,我也不能确定,因为我没有查看底层代码,但是在我更新了原始上下文并返回之后问题就消失了。谢谢。

【讨论】:

  • 已经很久了,但是请您再解释一下您的解决方案吗? :) 谢谢
  • 我遇到了同样的问题,但对我来说问题是 django-debug-toolbar 似乎创建了自己的 RequestContext 导致所有上下文处理器再次运行。我在 grepping 源时找不到 RequestContext,但从 INSTALLED_APPS 和 MIDDLEWARE_CLASSES 中删除它肯定解决了这个问题。
【解决方案4】:

这发生在生产网络服务器、Apache 等,还是仅在内置开发服务器中?我注意到有时在本地有类似的行为,但我很确定这只是运行服务器中的一个怪癖。

【讨论】:

    【解决方案5】:

    希望这会有所帮助:

    在我的情况下,问题是一个模板标签,即:来自 allauth 包的 providers_media_js。

    尽量不要在上下文处理器中返回任何内容,看看问题是否仍然存在。然后尝试找出导致此问题的变量。

    【讨论】:

      【解决方案6】:

      供将来参考——我的问题是视图函数中的render_to_string,导致上下文处理器被执行两次:

      comments = render_to_string('comments.html', {'comments': comments_list}, request)
      

      这个调用被缓存了,所以很难确定问题出在哪里。无论如何,我通过从 render_to_string 调用中删除请求上下文来解决它,因为在这种特殊情况下我不需要它:

      comments = render_to_string('comments.html', {'comments': comments_list})
      

      后来我重构了代码,把render_to_string全部去掉了,把sn-p直接缓存在模板里。但是在视图函数中使用render_to_string 是合法的(例如渲染电子邮件模板),所以这可能会导致一些问题。

      【讨论】:

        猜你喜欢
        • 2018-06-09
        • 2011-01-21
        • 1970-01-01
        • 2013-07-24
        • 1970-01-01
        • 1970-01-01
        • 2016-10-09
        • 2014-02-17
        • 2021-10-26
        相关资源
        最近更新 更多