自定义过滤器几行就能写完,但转义、异常、调用次数这三件事常被忽略。这篇写七个小过滤器,逐个验证它们在模板里的真实行为。
{{ v|shout }} → HI!
{{ v|add_str:"-x" }} → hi-x
链式 {{ v|shout|add_str:"?" }} → HI!?
变量作为参数 {{ v|add_str:suffix }} → hi_s
两个参数 → TemplateSyntaxError: Could not parse the remainder: ':"b"' from 'v|add_str:"a":"b"'过滤器就是普通函数,第一个参数是变量值,第二个(可选)是过滤器参数。
返回字符串的普通过滤器: <I>!
is_safe=True,输入是 safe: <i><end>
is_safe=True,输入不是 safe: <i><end>
needs_autoescape,自动转义开: <b><i></b>
needs_autoescape,{% autoescape off %} 里: <b><i></b>返回 HTML 的过滤器要么用 needs_autoescape 自己转义输入再 mark_safe,要么用 format_html;is_safe=True 只是「如果输入是 safe,输出仍是 safe」,不会让不安全的输入变安全。
boom 过滤器 → ValueError: filter exploded
变量不存在:{{ nope|shout }} → '!' ← 过滤器收到的是空字符串 "",于是得到 "!"
没有对应过滤器: TemplateSyntaxError: Invalid filter: 'nofilter'
对 None 用 len 的过滤器 → TypeError: object of type 'NoneType' has no len()模板里访问不存在的变量不报错(得到 string_if_invalid),但过滤器里的异常一定会传出来。
模板里写两次: 2
5 次循环: 5
{% with %} 先存下来再用两次: 1过滤器里做数据库查询或重计算时要注意调用次数。
没有 {% load myf %}: TemplateSyntaxError: Invalid filter: 'shout'templatetags 目录需要有 __init__.py,库名就是文件名。