详解Django框架中用context来解析模板的方法
你需要一段context来解析模板。 一般情况下,这是一个 django.template.Context 的实例,不过在Django中还可以用一个特殊的子类, django.template.RequestContext ,这个用起来稍微有些不同。 RequestContext 默认地在模板context中加入了一些变量,如 HttpRequest 对象或当前登录用户的相关信息。 当你不想在一系例模板中都明确指定一些相同的变量时,你应该使用 RequestContext 。 例如,考虑这两个视图: from django.template import loader,Context def view_1(request): # ... t = loader.get_template('template1.html') c = Context({ 'app': 'My app','user': request.user,'ip_address': request.META['REMOTE_ADDR'],'message': 'I am view 1.' }) return t.render(c) def view_2(request): # ... t = loader.get_template('template2.html') c = Context({ 'app': 'My app','message': 'I am the second view.' }) return t.render(c) (注意,在这些例子中,我们故意 不 使用 render_to_response() 这个快捷方法,而选择手动载入模板,手动构造context对象然后渲染模板。 是为了能够清晰的说明所有步骤。) 每个视图都给模板传入了三个相同的变量:app、user和ip_address。 如果我们把这些冗余去掉会不会更好? 创建 RequestContext 和 context处理器 就是为了解决这个问题。 Context处理器允许你设置一些变量,它们会在每个context中自动被设置好,而不必每次调用 render_to_response() 时都指定。 要点就是,当你渲染模板时,你要用 RequestContext 而不是 Context 。 最直接的做法是用context处理器来创建一些处理器并传递给 RequestContext 。上面的例子可以用context processors改写如下: from django.template import loader,RequestContext def custom_proc(request): "A context processor that provides 'app','user' and 'ip_address'." return { 'app': 'My app','ip_address': request.META['REMOTE_ADDR'] } def view_1(request): # ... t = loader.get_template('template1.html') c = RequestContext(request,{'message': 'I am view 1.'},processors=[custom_proc]) return t.render(c) def view_2(request): # ... t = loader.get_template('template2.html') c = RequestContext(request,{'message': 'I am the second view.'},processors=[custom_proc]) return t.render(c) 我们来通读一下代码: 首先,我们定义一个函数 custom_proc 。这是一个context处理器,它接收一个 HttpRequest 对象,然后返回一个字典,这个字典中包含了可以在模板context中使用的变量。 它就做了这么多。 我们在这两个视图函数中用 RequestContext 代替了 Context 。在context对象的构建上有两个不同点。 一, RequestContext 的第一个参数需要传递一个 HttpRequest 对象,就是传递给视图函数的第一个参数( request )。二, RequestContext 有一个可选的参数 processors ,这是一个包含context处理器函数的列表或者元组。 在这里,我们传递了我们之前定义的处理器函数 curstom_proc 。 每个视图的context结构里不再包含 app 、 user 、 ip_address 等变量,因为这些由 custom_proc 函数提供了。 每个视图 仍然 具有很大的灵活性,可以引入我们需要的任何模板变量。 在这个例子中, message 模板变量在每个视图中都不一样。 为了讲解context处理器底层是如何工作的,在上面的例子中我们没有使用 render_to_response() 。但是建议选择 render_to_response() 作为context的处理器。这就需要用到context_instance参数: from django.shortcuts import render_to_response from django.template import RequestContext def custom_proc(request): "A context processor that provides 'app','ip_address': request.META['REMOTE_ADDR'] } def view_1(request): # ... return render_to_response('template1.html',context_instance=RequestContext(request,processors=[custom_proc])) def view_2(request): # ... return render_to_response('template2.html',processors=[custom_proc])) 在这,我们将每个视图的模板渲染代码写成了一个单行。 虽然这是一种改进,但是,请考虑一下这段代码的简洁性,我们现在不得不承认的是在 另外 一方面有些过分了。 我们以代码冗余(在 processors 调用中)的代价消除了数据上的冗余(我们的模板变量)。 由于你不得不一直键入 processors ,所以使用context处理器并没有减少太多的输入量。 Django因此提供对 全局 context处理器的支持。 TEMPLATE_CONTEXT_PROCESSORS 指定了哪些context processors总是默认被使用。这样就省去了每次使用 RequestContext 都指定 processors 的麻烦。 默认情况下, TEMPLATE_CONTEXT_PROCESSORS 设置如下: TEMPLATE_CONTEXT_PROCESSORS = ( 'django.core.context_processors.auth','django.core.context_processors.debug','django.core.context_processors.i18n','django.core.context_processors.media',) 这个设置项是一个可调用函数的元组,其中的每个函数使用了和上文中我们的 custom_proc 相同的接口,它们以request对象作为参数,返回一个会被合并传给context的字典: 接收一个request对象作为参数,返回一个包含了将被合并到context中的项的字典。 每个处理器将会按照顺序应用。 也就是说如果你在第一个处理器里面向context添加了一个变量,而第二个处理器添加了同样名字的变量,那么第二个将会覆盖第一个。 Django提供了几个简单的context处理器,有些在默认情况下被启用的。 django.core.context_processors.auth 如果 TEMPLATE_CONTEXT_PROCESSORS 包含了这个处理器,那么每个 RequestContext 将包含这些变量:
关于users、permissions和messages的更多内容请参考第14章。 这个处理器把调试信息发送到模板层。 如果TEMPLATE_CONTEXT_PROCESSORS包含这个处理器,每一个RequestContext将包含这些变量:
细心的读者可能会注意到debug模板变量的值永远不可能为False,因为如果DEBUG是False,那么debug模板变量一开始就不会被RequestContext所包含。 如果这个处理器启用,每个 RequestContext 将包含下面的变量:
django.core.context_processors.request 如果启用这个处理器,每个 RequestContext 将包含变量 request , 也就是当前的 HttpRequest 对象。 注意这个处理器默认是不启用的,你需要激活它。 如果你发现你的模板需要访问当前的HttpRequest你就需要使用它: {{ request.REMOTE_ADDR }}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |