每个请求调用 Django 自定义上下文处理器两次
我创建了一个简单的自定义上下文处理器,只需运行 每个请求一次。添加一些日志挂钩后,我发现它 每个请求被调用两次。
这是文档中遗漏的已知“功能”吗? 与继承树中模板的数量有关吗? 是1.03的bug吗?
I created a simple custom context processor that needs to only be run
once per request. After putting in some logging hooks I found that it
is being called twice per request.
Is this a known "feature" that a missed in the docs?
Is it related to the number of templates in the inheritance tree?
Is it a bug in 1.03?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这不是预期的行为。上下文处理器每次实例化RequestContext时都会执行一次< /a>)。在模板继承的情况下,相同的上下文实例是传递到父模板,因此不会导致上下文处理器的另一次执行。您的日志记录具有误导性(请参阅@Vinay Sajip 的评论),或者您需要弄清楚代码中的哪个位置可能对每个请求执行额外的 RequestContext(您是否使用包含标签或其他一些呈现模板的自定义模板标签,并且实例化RequestContext?)
编辑 抱歉,“包含标签”我的意思是(在一般意义上)一些呈现另一个模板的标签,而不是任何使用inclusion_tag装饰器的标签。接受上下文的常规clusion_tag应该简单地传递现有的上下文对象,而不是实例化新的RequestContext。
您可以尝试的一件事是在上下文处理器中放置“import pdb; pdb.set_trace()”,在 Django 开发服务器中运行代码,并在每次上下文处理器命中时在控制台中使用 pdb 检查堆栈跟踪,查看它是从哪里调用的。
This is not expected behavior. Context processor are executed once each time a RequestContext is instantiated). In the case of template inheritance, the same context instance is passed up to the parent template, so that shouldn't cause another execution of the context processors. Either your logging is misleading (see @Vinay Sajip's comment), or you need to figure out where in your code an extra RequestContext might be executed on each request (are you using an inclusion tag or some other custom template tag that renders a template and instantiates RequestContext?)
EDIT Sorry, by "inclusion tag" I meant (in the generic sense) some tag that renders another template, not any tag that uses the inclusion_tag decorator. A regular inclusion_tag that takes context should simply pass along the existing context object, not instantiate a new RequestContext.
One thing you could try is to place an "import pdb; pdb.set_trace()" in your context processor, run the code in the Django dev server, and in the console examine the stack trace with pdb each time your context processor gets hit, to see where it's being called from.
就我而言,此错误在使用 django 时发生
debug_toolbar
。为了避免这种情况尝试发表评论In my case this bug occur when using
django
debug_toolbar
. To avoid this try to comment我想通了这个问题。如果返回原始上下文以外的字典,则上下文处理器似乎会再次执行。不知道为什么,我也不能确定,因为我没有查看底层代码,但在我更新原始上下文并返回后,问题就消失了。谢谢。
I figured out the issue. If a dictionary other than the original context is returned then the context processor seems to be executed again. Not sure why, and I can't be sure because I didn't look at the underlying code, but the after I updated the original context and returned that the issue went away. Thanks.
这种情况是发生在生产网络服务器、Apache 等上,还是仅仅发生在内置的开发服务器上?我偶尔在本地注意到类似的行为,但我很确定这只是运行服务器中的一个怪癖。
Is this happening on a production webserver, Apache etc, or just in the built in development server? I've noticed similar behaviour locally on occassion, but I'm pretty sure it's just a quirk in the runserver.
希望这会有所帮助:
就我而言,问题是模板标签,即:allauth 包中的providers_media_js。
尝试不要在上下文处理器中返回任何内容,并查看问题是否仍然存在。然后尝试找出哪个变量导致了这个问题。
Hope this helps:
In my case the issue was a templatetag, namely: providers_media_js from allauth package.
Try not to return anything in your context processor and see if the issue persists. Then try to spot which variable is responsible for this problem.
供将来参考——我的问题是视图函数内的 render_to_string ,导致上下文处理器被执行两次:
此调用被缓存,因此很难确定问题出在哪里。无论如何,我通过从
render_to_string
调用中删除请求上下文来解决这个问题,因为在这种特殊情况下我不需要它:后来我重构了代码并删除了
render_to_string
> 全部放在一起,并将代码片段直接缓存在模板中。但是在视图函数中使用 render_to_string 是合法的(例如渲染电子邮件模板),因此这可能会导致一些问题。For future reference -- my problem was a
render_to_string
inside a view function, causing the context processor to be executed twice:This call was cached, so it was kinda difficult to identify where the problem was. Anyway, I solved it by removing the request context from the
render_to_string
call, since I didn't need it for this particular case:Later on I refactored the code and removed the
render_to_string
all together, and cached the snippet directly in the template. But there are legit cases for usingrender_to_string
inside a view function (such as rendering an email template for example), so this may cause some issues.