Context 是一个传递给模版的名称到值的映射,类似python字典。
模版渲染就是通过从context获取值来替换模版中变量并执行所有的模版标签。
RequestContext默认的在模版context中加入了一些变量,如HttpRequest对象或当前登陆用户的相关信息。当你不想在一系列模版中都明确指定一些相同的变量时,应该使用RequestContext。例如考虑下面两个图:
from django.template import loader, Contextdef 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', 'user' : request.user, 'ip_address': request.META['REMOTE_ADDR'], 'message': 'I am view. }) return t.render(c)
我们故意不使用render_to_response() 这个快捷方法,手动的载入模版,手动构造context对象然后渲染模版,为了说清步骤。
每个视图中都给模版传入了三个相同的变量:app user ip_address, 怎么去掉这些冗余。
最直接的方法是用context处理器来处理与处理器并传递给RequestContext.改写如下:
from django.template import loader, RequestContextdef custom_proc(request): "A context processor that provides 'app', 'user' and 'ip_address'." return{ 'app' :'my_app', 'user':request.user, '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)
我们定义的custom_prom是一个context处理器,它接收一个HttpResponse对象,然后返回一个字典,这个字典中包含了可以在模版context中使用的变量。
使用RequestContext代替了Context。有两种不同点:RequestContext的第一个参数需要传递一个HttpResponse对象,有一个可选的参数processors,这是一个包含context处理器函数的列表或者元组,在这里,我们传递了我们之前定义的处理器函数custom_proc。
函数custom_proc提供了几个变量。每个视图仍然具有很大的灵活性,可以引入我们需要的任何模版变量。
之前我们都用render_to_response来代替调用loader.get_template(),然后创建一个context对象,最后再调用render()过程。底层的工作就是上边的例子。建议选择render_to_response作为context的处理器,这个时候用到:context_instance参数:
from django.shortcuts import render_to_responsefrom django.template import RequestContextdef custom_proc(request): " A context processor that provides 'app', 'users', and 'ip_address'." return { 'app': 'My app', 'user': request.user, 'ip_address': request.META['REMOTE_ADDR'] }def view_1(request): # ... return render_to_response('template1.html', { 'message': 'I am view 1.'}, context_instance=RequestContext(request, processors=[custom_proc]))def view_2(request): # ... return render_to_response('template2.html', { 'message': 'I am the second view.'}, context_instance=RequestContext(request, processors=[custom_proc]))
这里我们将每个视图的模版渲染代码写成了一行代码。
虽然这是一种改进,但是,请考虑一下这段代码的简洁性,我们现在不得不承认的是在 另外 一方面有些过分了。 我们以代码冗余(在 processors 调用中)的代价消除了数据上的冗余(我们的模板变量)。 由于你不得不一直键入 processors ,所以使用context处理器并没有减少太多的输入量。
django因此提供了全剧变量context处理器的支持,TEMPLATE_CONTEXT_PEOCESSORS指定了哪些context processors总是默认使用的,这样就省去了每次使用RequestContext都指定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处理器,有些在默认情况下被启用的。