过滤器本质上是 Python 的函数,他会把被过滤的值当作第一个参数传给这个函数,函数经过一些逻辑处理后,再返回新的值。在过滤器函数写好后,可以通过@app.template_filter
装饰器或者是app.add_template_filter
函数来把函数注册成 Jinja2 能用的过滤器。这里我们以注册一个时间格式化的过滤器为例,来说明下自定义过滤器的方法:
def datetime_format(value, format="%Y-%m-%d %H:%M"):
return value.strftime(format)
app.add_template_filter(datatime_format,"dformat")
上面我们定义了一个 datatime_format
的函数,第一个参数是需要被处理的值,第二个参数是时间的格式,并且指定了一个默认值。然后下面通过 app.add_template_filter
,将datatime_format
函数注册成了过滤器,并且这个过滤器的名字,叫做dformat
。那么以后在模板文件中,就可以直接类似于这样使用了:
{{article.pub_data | dformat }}
{{article.pub_data | dformat("%B %Y") }}
如果 app.add_template_filter
没有传第二个参数,那么默认使用函数的名称作为过滤器的名称。比如以上注册过滤器如果改成以下代码:
app.add_template_filter(datatime_format)
那么在模板中,就需要这样使用了:
{{article.pub_data | datatime_format }}
当然,我们也可以通过@app.template_filter
装饰器,在函数定义的时候,就将它注册成过滤器。比如以上的 datetime_format
函数,我们可以这样写:
@app.template_filter("dformat")
def datetime_format(value, format="%Y-%d-%m %H:%M"):
return value.strftime(format)
现在 datetime_format
被 @app.template_filter
装饰后,就会自动被注册进 Jinja2 的过滤器中。并且 @app.template_filter
中的参数即为自定义过滤器的名称,如果不传参数,也是会自动使用函数名称作为过滤器名称的。
Jinja2 内置过滤器官方文档:
https://jinja.palletsprojects.com/en/3.0.x/templates/#builtin-filters
abs(value)
:获取 value 的绝对值。default(value, default_value, boolean=False)
:如果 value 没有定义,则返回第二个参数 default_value 。如果想要让 value 在被判断为 False 的情况下使用 default_value,则应该将后面的 boolean 参数设置为 False。以下为示例:<div>default 过滤器:{{ user|default('admin')}}div>
如果 user 没有定义,那么将会使用 ‘admin’ 作为默认的值。
<div>default 过滤器:{{""|default('admin', boolean=True)}}div>
因为“”(空字符串)是一个放到 if 后面返回 False 的值,这时候如果想要使用默认值 ‘admin’,就必须加上 boolean=True 参数。
escape(value)
:将一些特殊字符,比如:&,<,>,”,’ 进行转义。因为 Jinja2 默认开启了全局转义,所以在大部分情况下无需手动使用这个过滤器去转义,只有在关闭转义的情况下,会需要使用到它。filesizeformate(value, binary=False)
:将值格式化成方便人类阅读的单位。比如 13KB、4.1MB、102Bytes 等。默认是 Mega、Giga,也就是每个相邻单位换算是1000倍。如果第二个参数设置为 True,那么相邻单位换算是1024倍。first(value)
:返回 value 的第一个元素。float(value, default=0.0)
:将 value 转换为浮点类型。如果转换失败会返回 0.0。format(value, *args, **kwargs)
:格式化字符串。{{"%s, %s" | format(greeting, name)}}
groupby(value, attribute, default=None)
:value 是一个序列,可以使用参数 attribute 进行分组。比如有一个 users 列表,里面的 User 都有一个 city 属性,那么按照 city 进行分组,则可以使用下列代码:<ul>
{% for group in users|groupby("city") %}
<li>{{ group.grouper }}: {{ group.list|join(",")}} li>
{% endfor %}
ul>
int(value, default=0, base=10)
:转换为整型,如果转换失败就返回 0 ,并且默认是按照十进制进行转换。join(value, attribute)
: 将一个序列,使用 attribute 指定的元素,拼接成一个字符串。跟 python 中的 join()
方法类似。last(value)
:返回 value 序列的最后一个元素。length(value)
:返回 value 序列的长度。list(value)
:转换 value 为一个序列。lower(value)
:将 value 全部转换为小写。map(value, *args, **kwargs)
:将 value 这个序列都执行某个操作。比如获取 users 这个序列中的每个 User 的 username 字段:{{ users|map(attribute='username')}}
比如想要将 titles 序列中每个元素的值都变为小写形式:
{{ titles|map('lower')}}
max(value)
:求序列的最大值。min(value)
:求序列的最小值。random(value)
:返回 value 这个序列中的一个随机值。reject(value, *args, **kwargs)
:过滤 value 这个序列中的一些元素。过滤的条件通过后面的参数给定。比如要过滤列表中所有的奇数,可以把 Jinja2 中内置的 odd 过滤器传给 reject 过滤器来实现:{{ numbers|reject(attribute('odd')}}
rejectattr(value, *args, **kwargs)
:根据 value 序列中元素上的某个属性进行过滤。只要这个属性满足条件,那么就会被过滤掉:{{ users|rejectattr(attribute('is_active')}}
{{ users|rejectattr(attribute('email','none')}}
第一个过滤的是 users 中 is_active 为 True 的对象,第二个是过滤掉 users 中 email 为 none 的对象。
repalce(value, old, new, count)
:将字符串 value 中的 old 替换为 new,并且可以通过 count 来确定替换多少个。跟 python 中字符串的 replace()
用法一致。reverse(value)
:将 value 这个序列逆序。safe(value)
:在渲染 value 的时候,关闭自动转义。比如:<div> safe 过滤器:{{"p>"| safe}}div>
因为加了 safe 过滤器,就不会对前面的字符串进行转义,前面的字符串就会被当成html 代码嵌入到网页中,从而看到一个红色的背景,背景中显示“中国”两个字。
select(value, *args, **kwargs)
:选择 value 序列中满足条件的元素。跟 reject()
正好相反。selectattr(value, *args, **kwargs)
:根据 value 序列中元素上的某个属性进行过滤,留下满足条件的,过滤掉不满足条件的。跟 rejectattr()
相反。sort(value, reverse=False, case_sensitive=False, attribute=None)
:将 value 这个序列进行排序,底层用的 python 的 sorted()
函数,reverse 表示是否逆向排序, case_sensitive 表示是否忽略大小写,attribute 表示根据 value 序列中元素的某个属性排序。string(value)
:将 value 转换为字符串类型。striptags(value)
:将字符串 value 中的 html 标签去除掉,留下文本内容。tojson(value)
:将 value 转换为 json 格式的字符串。trim(value)
:删除 value 前面和后面的空白字符。truncate(value, length=255, killword=False, end='...')
:将字符串 value 进行截取,length 表示保留多少个字符,killwords 表示在截取字符串的时候是否要裁剪单词, end 表示末尾的结束字符。unique(value, case_sensitive=False, attribute=None)
:将 value 序列中的重复元素删掉。upper(value)
:将 value 全部转换为大写。urlencode(value)
:如果 value 是字符串,那么底层会调用 python 的 urllib.parse.quote;如果 value 是字典,那么底层会调用 urllib.parse.urlencode。urlize(value, trim_url_limit=None, nofollow=False, target=None, rel=None, extra_schemes=None)
:将 value 变成可以点击的链接,比如 URL 和邮箱。前提是 value 必须是以 http://、https://、www 开头的字符串。wordcount(value)
:统计 value 中总共有多少个单词。xmlattr(value, autospace=True)
:value 为一个字典,根据这个字典,创建一个 xml 格式的属性,示例代码如下:<ul {{ {'class':'my_list', 'missing':none, 'id':'list-%d|format(variable)} |xmlattr}}>
···
ul>
过滤器可以嵌套使用:
{{ titles|map ('lower')| join('.')}}
在解析模板的时候,会先将 titles 传给 map 过滤器处理,得到的结果再传给 join 过滤器。