一、关于Django模板
之前洋洋洒洒写了一篇Django模板,但是“手➹”不小心给删除了。。。。今天重写一篇,就相当于总结。
---------------------------
注意:始终要知道模板template是Django提供的机制,里面有模板变量和模板标签,仅此而已!它解决在视图中HTML硬编码的问题,模板 是一个纯文本文件,或是一个用Django模板语言标记过的普通的Python字符串。
二、template模块
1 >>> from django import template #导入模板
1、创建模板对象
Template 类就在 django.template 模块中,构造函数接受一个参数。如:
1 t = template.Template('My name is {{ name }}.')
创建一个 Template 对象,模板系统在内部编译这个模板到内部格式,并做优化,做好 渲染的准备。
注意:如果模板语法有错误,那么在调用 Template() 时就会抛出 TemplateSyntaxError 异常
2、模板渲染
渲染 就是是通过从context获取值来替换模板中变量并执行所有的模板标签。
一旦创建一个 Template 对象,你可以用 context 来传递数据给它。 一个context是一系列变量和它们值的集合,类似字典Context 类在 django.template 模块里,她的构造函数带有一个可选的参数: 一个字典映射变量和它们的值。
调用 Template 对象 的 render() 方法并传递context来填充模板:
注意:t.render(c)返回的值是一个Unicode对象,不是普通的Python字符串。 可以通过字符串前的u来区分。 在框架中,Django会一直使用Unicode对象而不是普通的字符串。
当然,同一模板,还可以有多个上下文(即context)
3.句点查找规则:
1):字典类型查找 (比如 foo["bar"] )
2):属性查找 (比如 foo.bar )
3):方法调用 (比如 foo.bar() )
4):列表类型索引查找 (比如 foo[bar] )
如:
1 #用于访问列表索引 2 >>> from django.template import Template, Context 3 >>> t = Template('Item 2 is {{ items.2 }}.') 4 >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) 5 >>> t.render(c) 6 u'Item 2 is carrots.'
三、在视图中使用
参见:
Django学习笔记(4):Django模板系统(上)
Django学习笔记(5):Django模板系统(下)
四、RequestContext和Context处理器
from django.template import Context,RequestContext
RequestContext 默认地在模板context中加入了一些变量,如 HttpRequest 对象或当前登录用户的相关信息。
demo:
URL: urlpatterns = patterns('', (r'^test1/$','demo.views.t1'), (r'^test2/$','demo.views.t2'), )
使用Context和RequestContext区别,注意注释掉的部分是属于Context的,这里视图冗余,故使用RequestContext
#coding=utf-8 from django.http import HttpRequest,HttpResponse,HttpResponseRedirect from django.template import TemplateDoesNotExist,RequestContext,loader,Context,Template def custom_pro(request): '''app、user、IP''' return{ 'app':'My app', 'user':request.user, 'ip':request.META['REMOTE_ADDR'] } def custom_other_pro(request): '''name,age,job''' return{ 'name':'BeginMan', 'age':22, 'job':'Pythoner' } def t1(request): t=loader.get_template('test/t1.html') # c=Context({'app':'My app', # 'user':request.user, # 'ip':request.META['REMOTE_ADDR'], # 'message':'i am t1'}) c=RequestContext(request,{'message':'i am t1'},processors=[custom_pro]) return HttpResponse(t.render(c)) def t2(request): t=loader.get_template('test/t2.html') # c=Context({'app':'My app', # 'user':request.user, # 'ip':request.META['REMOTE_ADDR'], # 'message':'i am t2'}) c=RequestContext(request,{'message':'i am t2'},processors=(custom_pro,custom_other_pro))#元祖形式也行 return HttpResponse(t.render(c))
当然。也可以进行数据处理:
def custom_Msg(request): '''return Msg data''' msg=Msg.objects.all() return{'msg':msg}
分析:
1):定义custom_pro、custom_other_pro、 custom_Msg这些函数,其实都是context处理器,它接收一个 HttpRequest 对象,然后返回一个字典,这个字典中包含了可以在模板context中使用的变量。 它就做了这么多。
2):我们在这两个视图函数中用 RequestContext 代替了 Context 。在context对象的构建上有两个不同点。 一, RequestContext 的第一个参数需要传递一个 HttpRequest 对象,就是传递给视图函数的第一个参数( request )。二, RequestContext 有一个可选的参数 processors(处理器的意思) ,这是一个包含context处理器函数的列表或者元组。 在这里,我们传递了我们之前定义的处理器函数 custom_pro、custom_other_pro、 custom_Msg
3):如果还不明白,可以看看RequestContext的源码:
源码: class RequestContext(Context): """ This subclass of template.Context automatically populates itself using the processors defined in TEMPLATE_CONTEXT_PROCESSORS. Additional processors can be specified as a list of callables using the "processors" keyword argument. """ def __init__(self, request, dict=None, processors=None, current_app=None): Context.__init__(self, dict, current_app=current_app) if processors is None: processors = () else: processors = tuple(processors) for processor in get_standard_processors() + processors: self.update(processor(request))
接下来就开始处理模板了,这里列出了t2.html:
-------custom_pro<br> <div style="color:Red"> {{app}}<br> {{user}}<br> {{ip}}<br> {{message}}<br> </div> -------custom_other_pro<br> <div style="color:Blue"> {{name}}<br> {{age}}<br> {{job}} </div> <div style="color:#CCC"> {% for obj in msg %} <li>{{obj.title}}</li> {% endfor %} </div>
效果如下:
扩展:
render_to_response() 这个快捷方式,它可以简化调用 loader.get_template(),但是上面为了说明两者之间的区别,没有使用,这里我们还是要使用render_to_response(),此时要加入context_instance参数才能正常使用:
def t2(request): return render_to_response( 'test/t2.html', {'message':'t2'}, context_instance=RequestContext(request,processors=(custom_pro,custom_other_pro,custom_Msg))) # t=loader.get_template('test/t2.html') # c=RequestContext(request,{'message':'i am t2'},processors=(custom_pro,custom_other_pro,custom_Msg)) # return HttpResponse(t.render(c))
五、全局 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中的项的字典。
具体分析见下节