Django从1.7升级到1.8:需要来自视图中contextprocessor的变量

Django从1.7升级到1.8:需要来自视图中contextprocessor的变量,django,django-templates,django-1.8,Django,Django Templates,Django 1.8,在每次点击页面时,必须确定许多变量,但这些变量在我的项目中的不同位置使用,不仅在模板中,而且在视图中。到目前为止,我一直在使用上下文处理器(称为“globals”)来实现这个结果。请注意,在上下文处理器中,我正在进行实际计算和数据库调用,所以我不需要一个设置变量 自从从Django 1.7升级到1.8之后,上下文处理器返回的变量仍然显示在模板中,这很好,但它们不再显示在视图中,至少我找不到它们 在我的contextprocessor中,我有以下代码: def globals(request):

在每次点击页面时,必须确定许多变量,但这些变量在我的项目中的不同位置使用,不仅在模板中,而且在视图中。到目前为止,我一直在使用上下文处理器(称为“globals”)来实现这个结果。请注意,在上下文处理器中,我正在进行实际计算和数据库调用,所以我不需要一个设置变量

自从从Django 1.7升级到1.8之后,上下文处理器返回的变量仍然显示在模板中,这很好,但它们不再显示在视图中,至少我找不到它们

在我的contextprocessor中,我有以下代码:

def globals(request):

    # NOTE: We DON'T simply need a variable from settings - in reality this is computed
    if_this_is_true_then_we_alter_text = True

    ctx = {
        'var_from_contextprocessor': if_this_is_true_then_we_alter_text,
    }

    return ctx
那么,在我看来,我有:

from django.template import RequestContext
from django.shortcuts import render

def show_globals(request):
    ctx = RequestContext(request)
    ctx['var_from_view'] = 'YES, we found it!' if ctx.has_key('var_from_contextprocessor') else 'NO, it ain\'t there!'
    return render(request, 'show_globals.html', context_instance=ctx)
我的模板,
show_globals.html
如下所示:

var_from_view: {{ var_from_view }}
var_from_contextprocessor: {{ var_from_contextprocessor }}
运行Django 1.7时,来自视图的模板中的输出将是“YES,we found it!”。然而,一旦我升级到1.8,上下文处理器返回的变量似乎对视图可用,因此文本变为“不,它不在那里!”。但是,在这两种情况下,
var\u from_contextprocessor
会正确地显示在模板本身中

是否还有一种方法可以从各个视图中的上下文处理器检索变量?如果没有,您对如何在不使用上下文处理器的情况下实现相同的结果有何建议

请注意,我试图解决的基本问题只是在每次点击页面时动态计算变量,然后视图和模板都可以使用这些变量。我真的不在乎这是否是通过使用上下文处理器来完成的


提前谢谢

在1.7和1.8之间发生变化的是引入了不同的模板后端,以允许对eg Jinja2提供一流的支持。这意味着上下文处理器已经从顶级设置转移到与特定模板后端关联的设置;例如,模板上下文处理器设置已被弃用,但目前仍受支持

结果是,RequestContext在与实际模板关联之前,不会与任何特定的上下文处理器集相关联。默认情况下,调用模板的
render
方法时会发生这种情况(该方法本身由上面使用的独立
render
快捷方式调用)

但是,您可以通过显式调用
bind_template
并在视图中自己进行渲染来完成此操作:

from django.template import loader

ctx = RequestContext(request)
tpl = loader.get_template('show_globals.html')
with ctx.bind_template(tpl.template):
    ctx['var_from_view'] = 'YES, we found it!' if ctx.has_key('var_from_contextprocessor') else 'NO, it ain\'t there!'
    return HttpResponse(template.render(ctx))

但我必须说,这整件事让我觉得是对上下文处理器的滥用,而上下文处理器被称为模板上下文处理器是有原因的。您应该考虑重新编写代码,这样您就不需要在视图中使用此访问权限—也许可以在模板标记中执行此操作?

我发现了一个解决方案,至少在我的案例中是这样的

因此,理想的结果是生成代码,该代码在每次页面加载时运行,结果在所有视图和所有模板中都可用

Daniel Roseman的另一个回答很好地解释了为什么Django版本1.7和1.8之间的简单contextprocessor停止工作的一个技术原因,所以我在这里不赘述

长话短说,诀窍是使用中间件而不是contextprocessor,但随后让contextprocessor从中间件继承变量

考虑原始问题中的代码,与新代码进行比较:

上下文处理器:

def globals(request):

    ctx = request.extravars # See example.middleware.ExtraVarsMiddleware

    return ctx
中间件:

class ExtraVarsMiddleware():
    # For handing certain variables over to the context processor for global display.
    def process_view(self, request, view_func, view_args, view_kwargs):

        # NOTE: We DON'T simply need a variable from settings
        if_this_is_true_then_we_alter_text = True

        request.extravars = {
            'var_from_contextprocessor': if_this_is_true_then_we_alter_text,
        }
“全局”变量挂接到一个名为extravars的任意命名字典中的请求对象上。请注意,虽然我们的“全局”变量条目仍然被称为来自上下文处理器的
var\u
,但在这一点上,这是一个误称,因为它来自中间件,而不再是上下文处理器

为了激活此中间件,必须更改设置以包括它,如下所示(包括默认值):

由于上下文处理器已将整个
request.extravars
添加到其生成的上下文中,然后根据上面的代码返回,因此模板可以像以前一样访问变量

然后,为了访问视图中的变量,我们需要对之前的内容做一点更改:

from django.shortcuts import render

def show_globals(request):
    ctx = request.extravars
    ctx['var_from_view'] = 'YES, we found it!' if ctx.has_key('var_from_contextprocessor') else 'NO, it ain\'t there!'
    return render(request, 'show_globals.html', context=ctx)
我已经尽可能少地修改了这段代码,以演示所需的最小更改。只有两件事发生了变化,一件是如何获取
ctx
字典,这次没有使用
RequestContext
。第二个变化是,我们不再将
context\u实例
传递给
render
函数,而是简单地传递
context

为了澄清,我的示例设置中相应的文件名如下:

example/contextprocessors.py
example/middleware.py
example/views.py
settings.py

谢谢你提供的信息!您已经澄清了这背后的原因。:)我不太确定什么才算是误用,但我确切的问题是,我需要在视图函数和模板中使用一些东西,但这些都是我在每个页面上使用的变量,因此我发现在每个视图函数中做一些事情来实现这一点非常讨厌。一般来说,我不喜欢编写另一个视图函数时需要重复。不过,我已经发现了如何达到预期的效果,并将在另一封回复中为其他人发布。:)长话短说,改用中间件。
example/contextprocessors.py
example/middleware.py
example/views.py
settings.py