Django Template的if标签
在Django的早期版本中,if标签的功能不是太强,只能检查一个变量是否为真(即,变量存在,非空,不是布尔值假),不支持==、!=、>、>=、<、<=等比较。如果要比较两个值是否相等,就要使用ifequal标签。
在Django模板系统中,以下这些对象相当于布尔值的False1
2
3
4
5
6
7空列表([])
空元组(())
空字典({})
空字符串('')
零值(0)
特殊对象None
对象False
除这些之外都被视为True。if标签还接受and、or和not来对多个变量做判断,但是and和or不能混用,因为可能会造成逻辑混乱,因为if标签不支持通过()来改变运算优先级。
不过在较高版本的Django中,这些都得到了不同程度的改善。例如:1. 支持==、>这些运算符来对两个对象进行比较;2. and和or可以混用,但是注意一点,and运算的优先级更高。不过由于if标签还是不支持(),所以还是尽量把运算放在后端而不要混用and和or。
Django Template中的变量
在Django Template中,我们通过上下文传入的变量,但是变量调用方法时会受到一定的限制,变量只能调用无参的方法,如一个str对象,它只能调用如upper之类的无参对象,调用方式如下:1
2
3
4{{ string.upper }} # correct
{{ string.upper() }} #error
{{ string.index('a') }} #error
{{ string[0:-1]}} #error
对于一个可索引对象,如list、set、dict等,我们在Template中可以通过以下方式获得其中的指定对象:1
2
3{{ list.0 }} # list[0]
{{ set.0 }} # set[0]
{{ dict.a }} # dict['a']
Django Template自定义过滤器
Django利用过滤器大大强化了Template的功能,在Template利用管道符|
来调用,调用的一般形式如下:1
2{{ value | filter }} # 没有额外的参数
{{ value | filter : arg }} #带有一个额外的参数
其中,value
是变量,arg
为选项值
不过在很多情况下,我们需要自定义一些过滤器,我们在我们的一个app目录建立templatetags/在此目录下建立空文件init.py和myfilter.py,首先插入几行代码:1
2from django import template
register = template.Library()
其中register
是用来注册过滤器的,过滤器函数必须要返回一些信息,即使出错,也要返回空字符串或者默认值,过滤器分为有参和无参两种:
1 | def remove(value, arg): |
接下去的我们我们要注册自定义的过滤器:
1 | # 第一个参数是在模板中使用的过滤器的名字 |
在Python2.4以上的版本中,可以使用装饰器来注册:
1 | @register.filter(name='remove') |
如果要指定传入的value的类型,也可以使用装饰器:
1 | from django.template.defaultfilters import stringfilter |
最终,完整的代码如下:
1 | from django import template |
然而我们在Template中使用自定义的过滤器时,要先加这一段代码:1
{% load myfilter %}
Django Template自定义标签
Django中的自定义标签要比自定义过滤器复杂不少,在开始之前,我们先大概了解下Django Template的编译过程,当Django去编译一个Template时,它会把内容转成一个个django.template.Node实例,每个实例都有一个render方法,因此一个Template可以看做是一个Node的列表。当一个模板被渲染时,Template中Node实例的render方法会被调用,最终的返回会被合并。所以我们自定义标签就需要去实现我们自己的Node类和render方法。
我们动手来写一个标签,调用方式如下:
1 | {% current_time "%Y-%m-%D %I:%M %p" %} |
首先还是要写这几句代码用来注册(我们把这部分代码放入自定义myfilter.py中,这两行就可以省略了):
1 | from django import template |
我们定义一个Node类:
1 | class CurrentTimeNode(template.Node): |
然后定义一个编译函数用来创建Node实例:
1 | def do_current_time(parser, token): |
每一个标签的编译函数都需要parser和token两个函数,parser是模板分析对象,token为分析后的内容,可以直接使用。token.contents为标签的内容,token.split_contents会按空格分割token的内容,返回一个tuple,不过会保留‘“’,使用时要注意。其中token.split_contents()[0]可以得到标签名。
然后我们要注册一下标签:
1 | @register.tag(name="current_time") 仅限Python2.4以上 |
Template中使用时依然要加上:
1 | {% load myfilter %} |
自定义标签还有一些更高级的用法,我们在后续的blog中再讲。。
参考
官方文档:https://docs.djangoproject.com/en/1.9/howto/custom-template-tags/