购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

4.2 过滤器和测试器

在Python中,如果需要对某个变量进行处理,可以通过函数来实现,而在模板中,则是通过过滤器来实现的。过滤器本质上也是函数,但是在模板中使用的方式是通过管道符号(|)来调用的。例如,有一个字符串类型的变量name,要获取它的长度,可以通过{{ name|length }}来获取,Jinja2会把name当作第1个参数传给length过滤器底层对应的函数。length是Jinja2内置好的过滤器,Jinja2中内置了许多好用的过滤器,如果内置的过滤器不能满足需求,还可以自定义过滤器。下面先来学习如何自定义过滤器,读者明白了过滤器的原理后,再去学习Jinja2内置的过滤器就会更加得心应手了。

4.2.1 自定义过滤器

过滤器本质上是Python的函数,它会把被过滤的值当作第1个参数传给这个函数,函数经过一些逻辑处理后,再返回新的值。过滤器函数写好后可以通过@app.template_filter装饰器或者app.add_template_filter函数把函数注册成Jinja2能用的过滤器。这里以注册一个时间格式化的过滤器为例,来说明自定义过滤器的方法,示例代码如下。

    def datetime_format(value, format="%Y-%d-%m %H:%M"):
       return value.strftime(format)
     
    app.add_template_filter(datetime_format,"dformat")

在上面代码中定义了一个datetime_format函数,第1个参数是需要被处理的值,第2个参数是时间的格式,并且指定了一个默认值。下面通过app.add_template_filter将datetime_format函数注册成了过滤器,过滤器的名字叫作dformat。那么以后在模板文件中,就可以按如下方式使用了。

    {{ article.pub_date|dformat }}
    {{ article.pub_date|dformat("%B %Y") }}

如果app.add_template_filter没有传第2个参数,那么默认将使用函数的名称作为过滤器的名称。如以上注册过滤器代码可以改成以下代码。

    ...
    app.add_template_filter(datetime_format)

在模板中则按以下方式使用。

    {{ article.pub_date|datetime_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中的参数即为自定义过滤器的名称,如果不传参数,也会自动使用函数名称作为过滤器的名称。

4.2.2 Jinja2内置过滤器

在理解了Jinja2过滤器的原理后,再来学习Jinja2中内置过滤器,读者无须全部记住这些过滤器,只需在使用的时候翻阅本书或者阅读Jinja2官方文档https://jinja.palletsprojects.com/en/3.0.x/templates/#builtin-filters即可,用的次数多了自然会记住。

Jinja2中内置过滤器如下。

(1)abs(value):获取value的绝对值。

(2)default(value,default_value,boolean=False):如果value没有定义,则返回第2个参数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参数。

(3)escape(value):将一些特殊字符,如&、<、>、"、'进行转义。因为Jinja2默认开启了全局转义,所以在大部分情况下无须手动使用这个过滤器去转义,只有在关闭了转义的情况下,会需要使用到它。

(4)filesizeformat(value,binary=False):将值格式化成方便阅读的单位。如13KB、4.1MB、102Bytes等。默认是Mega、Giga,也就是每个相邻单位换算是1000倍。如果第2个参数设置为True,那么相邻单位换算是1024倍。

(5)first(value):返回value序列的第1个元素。

(6)float(value,default=0.0):将value转换为浮点类型,如果转换失败会返回0.0。

(7)format(value,*args,**kwargs):格式化字符串,示例代码如下。

    {{ "%s,%s"|format(greeting,name) }}

(8)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>

(9)int(value,default=0,base=10):转换为整型,如果转换失败会返回0,并且默认按照十进制转换。

(10)join(value,attribute):使用attribute指定的元素,将一个序列拼接成一个字符串。与Python中的join方法类似。

(11)last(value):返回value序列的最后一个元素。

(12)length(value):返回value序列的长度。

(13)list(value):转换value为一个列表。

(14)lower(value):将value全部转换为小写。

如要将titles序列中每个元素的值都变成小写形式,那么可以使用以下代码实现。

    {{ titles|map('lower')}}

(15)map(value,*args,**kwargs):将value这个序列都执行某个操作。如获取users这个序列中每个user的username字段。可以通过以下代码实现。

    {{ users|map(attribute='username') }}

(16)max(value):求序列中的最大值。

(17)min(value):求序列中的最小值。

(18)random(value):返回value这个序列中的一个随机值。

(19)reject(value,*args,**kwargs):过滤value这个序列中的一些元素,过滤的条件通过后面的参数给定。如要过滤列表中所有的奇数,可以把Jinja2中内置的odd过滤器传给reject过滤器来实现,代码如下。

    {{ numbers|reject ('odd') }}

(20)rejectattr(value,*args,**kwargs):根据value序列中元素的某个属性进行过滤。只要这个属性满足条件,那么就会被过滤掉,示例代码如下。

    {{ users|rejectattr("is_active") }}
    {{ users|rejectattr("email", "none") }}

上面第1行代码是过滤users中is_active为True的对象,第2行代码是过滤users中email为none的对象。

(21)replace(value,old,new,count):将字符串value中的old替换为new,并且可以通过count来确定替换多少个。与Python中字符串的replace方法用法一致。

(22)reverse(value):将value这个序列逆序。

(23)safe(value):在渲染value时,关闭自动转义。如以下代码所示。

    <div>safe过滤器:{{ "<p style='background-color: red;'>中国</p>"|safe }}
    </div>

因为加了safe过滤器,就不会对前面的字符串进行转义,前面的字符串就会被当成HTML代码嵌入网页,从而看到一个红色的背景,背景中显示“中国”两个文字。

(24)select(value,*args,**kwargs):选择value序列中满足条件的元素,与reject正好相反。

(25)selectattr(value,*args,**kwargs):根据value序列中元素的某个属性进行过滤,留下满足条件的,过滤掉不满足条件的,与rejectattr正好相反。

(26)sort(value,reverse=False,case_sensitive=False,attribute=None):将value这个序列进行排序,底层用的是Python的sorted函数,reverse代表是否逆向排序,case_sensitive代表是否忽略大小写,attribute代表根据value序列中元素的某个属性排序。

(27)string(value):将value转换为字符串类型。

(28)striptags(value):将字符串value中的HTML标签去除,留下文本内容。

(29)tojson(value):将value转换为JSON格式的字符串。

(30)trim(value):删除value前面和后面的空白字符(空格)。

(31)truncate(value,length=255,killwords=False,end="…"):将字符串value进行截取,length代表保留多少个字符,killwords代表在截取字符串时是否要裁剪单词,end代表末尾的结束字符。这在文章简介、个人简介等只需要显示一部分字符的场景下非常有用。

(32)unique(value,case_sensitive=False,attribute=None):将value序列中的重复元素删除。case_sensitive代表是否忽略大小写,attribute代表使用value序列中元素的某个属性。

(33)upper(value):将value所有字符全部转换为大写。

(34)urlencode(value):如果value是字符串,那么底层会调用Python的urllib.parse.quote;如果value是字典,那么底层会调用Python的urllib.parse.urlencode。

(35)urlize(value,trim_url_limit=None,nofollow=False,target=None,rel=None,extra_schemes=None):将value变成可以单击的链接,如URL和邮箱。注意:value必须是以http://、https://、www.、mailto开头的字符串。

(36)wordcount(value):统计value中共有多少个单词。

(37)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过滤器。

4.2.3 测试器

测试器用来测试某些元素是否满足某个条件,如测试一个变量是否是字符串、测试一个变量能否被调用等。以下代码通过演示defined测试器,来讲解测试器的使用。

    {% if user is defined %}
       user定义了 : {{ user }}
    {% else %}
        user没有定义
    {% endif %}

可以看到,测试器是通过if…is…来使用的,if后面是被测试的对象,is后面是测试器。除了defined测试器,Jinja2还提供了如表4-1所示的测试器。

表4-1 测试器

表4-1所示的测试器是Jinja2模板中内置的所有测试器,与过滤器的学习方式一样,读者可先简单阅读,无须强记,在需要使用时再翻阅Jinja2内置测试器的官方文档https://jinja.palletsprojects.com/en/3.0.x/templates/#list-of-builtin-tests即可。 lLwLRA3KDzBrklfquxIRwt4DTSP6Tauv0qCIoAxrg0clfTsry9MCbnp6pz1XM7Cb

点击中间区域
呼出菜单
上一章
目录
下一章
×