我做了两个Django项目,都遇到这样一个简单的需求,传一个数字m到模版,希望模版能执行一个m次的for循环。看似简单,但是如果不自定义模版,就必需在view里把m编程mlist = range(m)传到前台,前台再通过filter {{mlist|length}}获得原来的m。虽然这个参数的传递对性能的影响很有限,但是总把m编程range(m)就比较郁闷了,也不符合Django don't repeat yourself的哲学。
那么有filter或者tag可以实现这个功能吗,我曾经找到一个build-in的filter叫作make_list,结果它仅仅是将m变成[m]而已。只好手动实现一个。
在application的目录下新建一个目录,据definitive guide to django的例子,目录名叫templatetags,我还没有测试是否一定要用这个名字,暂且先这样命名。无需在setting等文件中声明,只需在目录下建立一个__init__.py,使程序可以访问即可。接下来就可以在其中创建任意名的py程序文件,如mytags.py。
定义一个filter叫作range_num,代码非常简单
from django import template
register = template.Library()
@register.filter(name='range_num')
def range_num(value):
return range(value)
Template文件中要调用此filter,只需增加一个tag,参数名文自定义tag的文件名
{% load mytag %}
编写Tag
tag的写法与filter类似,但是要复杂不少,具体可以参考django的文档。不过通常情况下,自定义filters加build-in的tags就已经非常强大了。

