模板-过滤器&标签
模板值过滤器
对一个 Python开发者来说,写一个自己的模板语言就象是某种“成人礼”一样! 如果你还没有完成一个自己的 模板语言,好好考虑写一个,这是一个非常有趣的锻炼。
模板过滤器是在变量被显示前修改它的值的一个简单方法。 过滤器使用管道字符,如下所示:
{{ name|lower }}
过滤管道可以被* 套接* ,既是说,一个过滤器管道的输出又可以作为下一个管道的输入,如此下去。 下面的例子实现查找列表的第一个元素并将其转化为大写。
{{ my_list|first|upper }}
有些过滤器有参数。 过滤器的参数跟随冒号之后并且总是以双引号包含。
{{ bio|truncatewords:"30" }}
语法: | {{obj|filter__name:param}} |
Default | 如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如: {{ value|default:"nothing" }} |
Length |
返回值的长度。它对字符串和列表都起作用。例如:
{{ value|length }}
如果 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。
|
Filesizeformat |
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:
{{ value|filesizeformat }}
如果 value 是 123456789,输出将会是 117.7 MB。
|
Date | 如果 value=datetime.datetime.now(){{ value|date:"Y-m-d" }} |
Slice |
如果 value="hello world"
{{ value|slice:"2:-1" }}
|
Truncatechars |
如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:要截断的字符数
例如:
{{ value|truncatechars:9 }}
|
Safe |
Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。比如:
value="<a href="">点击</a>"
{{ value|safe}}
|
addslashes : | 添加反斜杠到任何反斜杠、单引号或者双引号前面。 这在处理包含JavaScript的文本时是非常有用的。 |
这里简单介绍一些常用的模板的过滤器,更多详见
模板语法之标签
标签看起来像是这样的: {% tag %}。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})。
for标签
遍历每一个元素:
{% for person in person_list %}
<p>{{ person.name }}</p>
{% endfor %}
给标签增加一个 reversed 使得该列表被反向迭代:
{% for athlete in athlete_list reversed %}
...
{% endfor %}
遍历一个字典:
{% for key,val in dic.items %} <p>{{ key }}:{{ val }}</p> {% endfor %}
可以嵌套使用 {% for %} 标签
for ... empty
在执行循环之前先检测列表的大小是一个通常的做法, 因为这种做法十分常见,所以`` for`` 标签支持一个可选的`` {% empty %}`` 分句,通过它我们可以定义当列表为空时的输出内容
for?标签带有一个可选的{%?empty?%}?从句,以便在给出的组是空的或者没有被找到时,可以有所操作。
{% for person in person_list %} <p>{{ person.name }}</p> {% empty %} <p>sorry,no person here</p> {% endfor %}
`` forloop`` 模板变量
forloop.counter 总是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时 forloop.counter 将会被设置为1。
{% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %}
forloop.counter0 类似于 forloop.counter ,但是它是从0计数的。 第一次执行循环时这个变量会被设置为0。
forloop.revcounter 是表示循环中剩余项的整型变量。 在循环初次执行时 forloop.revcounter 将被设置为序列中项的总数。 最后一次循环执行中,这个变量将被置1。
forloop.revcounter0 类似于 forloop.revcounter ,但它以0做为结束索引。 在第一次执行循环时,该变量会被置为序列的项的个数减1。
forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为```` 在下面的情形中这个变量是很有用的:
{% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %}
forloop.last 是一个布尔值;在最后一次执行循环时被置为True。 一个常见的用法是在一系列的链接之间放置管道符(|)
{% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}
上面的模板可能会产生如下的结果:
Link1 | Link2 | Link3 | Link4
另一个常见的用途是为列表的每个单词的加上逗号。
Favorite places:
{% for p in places %}{{ p }}{% if not forloop.last %}, {% endif %}{% endfor %}
forloop.parentloop 是一个指向当前循环的上一级循环的 forloop 对象的引用(在嵌套循环的情况下)。 例子在此:
{% for country in countries %} <table> {% for city in country.city_list %} <tr> <td>Country #{{ forloop.parentloop.counter }}</td> <td>City #{{ forloop.counter }}</td> <td>{{ city }}</td> </tr> {% endfor %} </table> {% endfor %}
forloop 变量仅仅能够在循环中使用。 在模板解析器碰到{% endfor %}标签后,forloop就不可访问了。
ifequal/ifnotequal
{% ifequal %} 标签比较两个值,当他们相等时,显示在 {% ifequal %} 和 {% endifequal %} 之中所有的值。
下面的例子比较两个模板变量 user 和 currentuser :
{% ifequal user currentuser %} <h1>Welcome!</h1> {% endifequal %}
参数可以是硬编码的字符串,随便用单引号或者双引号引起来
{% ifequal section 'sitenews' %} <h1>Site News</h1> {% endifequal %} {% ifequal section "community" %} <h1>Community</h1> {% endifequal %}
和 {% if %} 类似, {% ifequal %} 支持可选的 {% else%} 标签
{% ifequal section 'sitenews' %} <h1>Site News</h1> {% else %} <h1>No News Here</h1> {% endifequal %}
只有模板变量,字符串,整数和小数可以作为 {% ifequal %} 标签的参数
if/else
{% if %} 标签检查(evaluate)一个变量,如果这个变量为真(即,变量存在,非空,不是布尔值假),系统会显示在 {% if %} 和 {% endif %} 之间的任何内容,例如
{% if today_is_weekend %} <p>Welcome to the weekend!</p> {% endif %} {% else %} 标签是可选的: {% if today_is_weekend %} <p>Welcome to the weekend!</p> {% else %} <p>Get back to work.</p> {% endif %} {% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。 {% if num > 100 or num < 0 %} <p>无效</p> {% elif num > 80 and num < 100 %} <p>优秀</p> {% else %} <p>凑活吧</p> {% endif %}
Python 的“真值”
在Python和Django模板系统中,以下这些对象相当于布尔值的False
空列表([] ) ,空元组(() ) , 空字典({} ) ,空字符串('' ), 零值(0 ), 特殊对象None, 对象False(很明显)
提示:你也可以在自定义的对象里定义他们的布尔值属性(这个是python的高级用法)。
除以上几点以外的所有东西都视为`` True``
{% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反( not )
{% if %} 标签不允许在同一个标签中同时使用 and 和 or ,因为逻辑上可能模糊的,例如,如下示例是错误的: 比如这样的代码是不合法的:
{% if athlete_list and coach_list or cheerleader_list %}
系统不支持用圆括号来组合比较操作。 如果你确实需要用到圆括号来组合表达你的逻辑式,考虑将它移到模板之外处理,然后以模板变量的形式传入结果吧。 或者,仅仅用嵌套的{% if %}标签替换吧,就像这样:
{% if athlete_list %} {% if coach_list or cheerleader_list %} We have athletes, and either coaches or cheerleaders! {% endif %} {% endif %}
多次使用同一个逻辑操作符是没有问题的,但是我们不能把不同的操作符组合起来
并没有 {% elif %} 标签, 请使用嵌套的`` {% if %}`` 标签来达成同样的效果:
一定要用 {% endif %} 关闭每一个 {% if %} 标签。
With
使用一个简单地名字缓存一个复杂的变量,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的
例如:
{% with total=business.employees.count %} {{ total }} employee{{ total|pluralize }} {% endwith %
csrf_token
这个标签用于跨站请求伪造保护
不想让别人随意给这个服务器发送post请求
可以在form标签内部加上 {{csrf_token}}
rander将{{csrf_token}}标签渲染为一个type=hidden的input标签,在点击post提交请求时,会多提交一个键值对,Django的中间件会根据这个键值对来确定访问的安全性
自定义标签与过滤器
1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.
2、在app中创建templatetags模块(模块名只能是templatetags)
3、创建任意 .py 文件,如:my_tags.py
from django import template from django.utils.safestring import mark_safe register = template.Library()?? #register的名字是固定的,不可改变 @register.filter def filter_multi(v1,v2): return? v1 * v2 @register.simple_tag def simple_tag_multi(v1,v2): return? v1 * v2 @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result) from django import template from django.utils.safestring import mark_safe register = template.Library()?? #register的名字是固定的,不可改变 @register.filter def filter_multi(v1,v2): return? v1 * v2 @register.simple_tag def simple_tag_multi(v1,v2): return? v1 * v2 @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result)
自定义的过滤器只能传两个参数,而标签可以传多个
4、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py
{% load my_tags %}
5、使用simple_tag和filter(如何调用)
-------------------------------.html
{% load xxx %}??
??????
# num=12
{{ num|filter_multi:2 }} #24
{{ num|filter_multi:"[22,333,4444]" }}
{% simple_tag_multi 2 5 %}? 参数不限,但不能放在if for语句中
{% simple_tag_multi num 5 %}
注意:filter可以用在if等语句后,simple_tag不可以
{% if num|filter_multi:30 > 100 %}
{{ num|filter_multi:30 }}
{% endif %}
注释
注释使用 {# #}, 用这种语法的注释不能跨越多行。 这个限制是为了提高模板解析的性能 :
{# This is a comment #}
如果要实现多行注释,可以使用`` {% comment %}`` 模板标签,就像这样:
{% comment %} This is a multi-line comment. {% endcomment %}