方法调用要比其他的查询稍微复杂一点,下面是需要记住的几点:
1,在方法查询的时候,如果一个方法触发了异常,这个异常会传递从而导致渲染失
败,但是如果异常有一个值为True的silent_variable_failure
属性,这个变量会渲染成空string:
代码
1 | >>> t = Template("My name is {{ person.first_name }}.") |
2,方法调用仅仅在它没有参数时起作用,否则系统将继续查找下一个类型(列表索引查询)
3,显然一些方法有副作用,让系统访问它们是很愚蠢的,而且很可能会造成安全性问题。
例如你有一个BankAccount对象,该对象有一个delete()方法,模板系统不应该允许做下面的事情
1 | I will now delete this valuable data. {{ account.delete }} |
为了防止这种状况,可以在方法里设置一个方法属性alters_data
如果设置了alters_data=True
的话模板系统就不会执行这个方法:
代码
1 | def delete(self): |
不合法的变量怎样处理
默认情况下如果变量不存在,模板系统会把它渲染成空string,例如:
代码
1 | >>> from django.template import Template, Context |
系统会静悄悄地显示错误的页面,而不是产生一个异常,因为这种情况通常是人为的错误。
在现实情形下,一个web站点因为一个模板代码语法的错误而变得不可用是不可接受的。
我们可以通过设置Django配置更改Django的缺省行为,第10章扩展模板引擎会我们会讨论这个
玩玩Context对象
大多数情况下你初始化Context对象会传递一个字典给Context()
一旦你初始化了Context,你可以使用标准Python字典语法增减Context对象的items:
代码
1 | >>> from django.template import Context |
Context对象是一个stack,你可以push()和pop()
如果你pop()的太多的话它将触发django.template.ContextPopException:
代码
1 | >>> c = Context() |
if/else
{% if %}
标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值
系统则会显示{% if %}
和{% endif %}
间的所有内容:
代码
1 | {% if today_is_weekend %} |
{% if %}
标签接受and,or或者not来测试多个变量值或者否定一个给定的变量,例如:
代码
1 | {% if athlete_list and coach_list %} |
{% if %}
标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:
代码
1 | {% if athlete_list and coach_list or cheerleader_list %} |
如果你想结合and和or来做高级逻辑,只需使用嵌套的{% if %}
标签即可:
代码
1 | {% if athlete_list %} |
多次使用同一个逻辑符号是合法的:
代码
1 | {% if athlete_list or coach_list or parent_list or teacher_list %} |
没有{% elif %}
标签,使用嵌套的{% if %}
标签可以做到同样的事情:
代码
1 | {% if athlete_list %} |
确认使用{% endif %}
来关闭{% if %}
标签,否则Django触发TemplateSyntaxError
for
{% for %}
标签允许你按顺序遍历一个序列中的各个元素
Python的for语句语法为for X in Y,X是用来遍历Y的变量
每次循环模板系统都会渲染{% for %}
和{% endfor %}
之间的所有内容
例如,显示给定athlete_list变量来显示athlete列表:
代码
1 | <ul> |
在标签里添加reversed来反序循环列表:
代码
1 | {% for athlete in athlete_list reversed %} |
{% for %}
标签可以嵌套:
1 | {% for country in countries %} |
系统不支持中断循环,如果你想这样,你可以改变你想遍历的变量来使得变量只包含你想遍历的值
类似的,系统也不支持continue语句
{% for %}
标签内置了一个forloop模板变量,这个变量含有一些属性可以提供给你一些关于循环的信息
1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1,例如:
代码
1 | {% for item in todo_list %} |
2,forloop.counter0类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3,forloop.revcounter表示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1
4,forloop.revcounter0类似于forloop.revcounter,但它是表示的数量少一个,即最后一次循环时设为0
5,forloop.first当第一次循环时值为True,在特别情况下很有用:
代码
1 | {% for object in objects %} |
6,forloop.last当最后一次循环时值为True
代码
1 | {% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %} |
7,forloop.parentloop在嵌套循环中表示父循环的forloop:
代码
1 | {% for country in countries %} |
富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}
时forloop就消失了
如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}
标签替代它
Django会在for标签的块中覆盖你定义的forloop变量的值
在其他非循环的地方,你的forloop变量仍然可用
我们建议模板变量不要使用forloop,如果你需要这样做来访问你自定义的forloop,你可以使用forloop.parentloop
ifequal/ifnotequal
Django模板系统并不是一个严格意义上的编程语言,所以它并不允许我们执行Python语句
然而在模板语言里比较两个值并且在他们一致的时候显示一些内容,确实是一个在常见不过的需求了——所以Django提供了ifequal标签。
{% ifequal %}
比较两个值,如果相等,则显示{% ifequal %}
和{% endifequal %}
之间的所有内容:
代码
1 | {% ifequal user currentuser %} |
参数可以是硬编码的string,单引号和双引号均可,下面的代码是合法的:
代码
1 | {% ifequal section 'sitenews' %} |
和{% if %}
一样,{% ifequal %}
标签支持{% else %}
代码
1 | {% ifequal section 'sitenews' %} |
其它的模板变量,strings,integers和小数都可以作为{% ifequal %}
的参数:
代码
1 | {% ifequal variable 1 %} |
其它的Python类型,如字典、列表或booleans不能硬编码在{% ifequal %}
里面,下面是不合法的:
代码
1 | {% ifequal variable True %} |
如果你需要测试某个变量是true或false,用