flask 模板 php,Flask的Jinja2模板引擎 — 过滤器(3rd)

我所了解的模板引擎大部分都会提供类似Jinja2过滤器的功能,只不过叫法不同罢了。比如PHP Smarty中的Modifiers(变量调节器或修饰器),FreeMarker中的Build-ins(内建函数),连AngularJS这样的前端框架也提供了Filter过滤器。它们都是用来在变量被显示或使用前,对其作转换处理的。可以把它认为是一种转换函数,输入的参数就是其所修饰的变量,返回的就是变量转换后的值。

过滤器使用

回到我们第一篇的例子,我们在模板中对变量name作如下处理:

Hello {{ name | upper }}!

1

Hello{{name|upper}}!

你会看到name的输出都变成大写了。这就是过滤器,只需在待过滤的变量后面加上”|”符号,再加上过滤器名称,就可以对该变量作过滤转换。上面例子就是转换成全大写字母。过滤器可以连续使用:

Hello {{ name | upper | truncate(3, True) }}!

1

Hello{{name|upper|truncate(3,True)}}!

现在name变量不但被转换为大写,而且当它的长度大于3后,只显示前3个字符,后面默认用”…”显示。过滤器”truncate”有3个参数,第一个是字符截取长度;第二个决定是否保留截取后的子串,默认是False,也就是当字符大于3后,只显示”…”,截取部分也不出现;第三个是省略符号,默认是”…”。

其实从例子中我们可以猜到,过滤器本质上就是一个转换函数,它的第一个参数就是待过滤的变量,在模板中使用时可以省略去。如果它有第二个参数,模板中就必须传进去。

内置过滤器 Builtin Filters

Jinja2模板引擎提供了丰富的内置过滤器。这里介绍几个常用的。

字符串操作

{# 当变量未定义时,显示默认字符串,可以缩写为d #}

{{ name | default('No name', true) }}

{# 单词首字母大写 #}

{{ 'hello' | capitalize }}

{# 单词全小写 #}

{{ 'XML' | lower }}

{# 去除字符串前后的空白字符 #}

{{ ' hello ' | trim }}

{# 字符串反转,返回"olleh" #}

{{ 'hello' | reverse }}

{# 格式化输出,返回"Number is 2" #}

{{ '%s is %d' | format("Number", 2) }}

{# 关闭HTML自动转义 #}

{{ 'name' | safe }}

{% autoescape false %}

{# HTML转义,即使autoescape关了也转义,可以缩写为e #}

{{ 'name' | escape }}

{% endautoescape %}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

{# 当变量未定义时,显示默认字符串,可以缩写为d #}

{{name|default('No name',true)}}

{# 单词首字母大写 #}

{{'hello'|capitalize}}

{# 单词全小写 #}

{{'XML'|lower}}

{# 去除字符串前后的空白字符 #}

{{'  hello  '|trim}}

{# 字符串反转,返回"olleh" #}

{{'hello'|reverse}}

{# 格式化输出,返回"Number is 2" #}

{{'%s is %d'|format("Number",2)}}

{# 关闭HTML自动转义 #}

{{'name'|safe}}

{%autoescapefalse%}

{# HTML转义,即使autoescape关了也转义,可以缩写为e #}

{{'name'|escape}}

{%endautoescape%}

数值操作

{# 四舍五入取整,返回13.0 #}

{{ 12.8888 | round }}

{# 向下截取到小数点后2位,返回12.88 #}

{{ 12.8888 | round(2, 'floor') }}

{# 绝对值,返回12 #}

{{ -12 | abs }}

1

2

3

4

5

6

7

8

{# 四舍五入取整,返回13.0 #}

{{12.8888|round}}

{# 向下截取到小数点后2位,返回12.88 #}

{{12.8888|round(2,'floor')}}

{# 绝对值,返回12 #}

{{-12|abs}}

列表操作

{# 取第一个元素 #}

{{ [1,2,3,4,5] | first }}

{# 取最后一个元素 #}

{{ [1,2,3,4,5] | last }}

{# 返回列表长度,可以写为count #}

{{ [1,2,3,4,5] | length }}

{# 列表求和 #}

{{ [1,2,3,4,5] | sum }}

{# 列表排序,默认为升序 #}

{{ [3,2,1,5,4] | sort }}

{# 合并为字符串,返回"1 | 2 | 3 | 4 | 5" #}

{{ [1,2,3,4,5] | join(' | ') }}

{# 列表中所有元素都全大写。这里可以用upper,lower,但capitalize无效 #}

{{ ['tom','bob','ada'] | upper }}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

{# 取第一个元素 #}

{{[1,2,3,4,5]|first}}

{# 取最后一个元素 #}

{{[1,2,3,4,5]|last}}

{# 返回列表长度,可以写为count #}

{{[1,2,3,4,5]|length}}

{# 列表求和 #}

{{[1,2,3,4,5]|sum}}

{# 列表排序,默认为升序 #}

{{[3,2,1,5,4]|sort}}

{# 合并为字符串,返回"1 | 2 | 3 | 4 | 5" #}

{{[1,2,3,4,5]|join(' | ')}}

{# 列表中所有元素都全大写。这里可以用upper,lower,但capitalize无效 #}

{{['tom','bob','ada']|upper}}

字典列表操作

{% set users=[{'name':'Tom','gender':'M','age':20},

{'name':'John','gender':'M','age':18},

{'name':'Mary','gender':'F','age':24},

{'name':'Bob','gender':'M','age':31},

{'name':'Lisa','gender':'F','age':19}]

%}

{# 按指定字段排序,这里设reverse为true使其按降序排 #}

{% for user in users | sort(attribute='age', reverse=true) %}

{{ user.name }}, {{ user.age }}

{% endfor %}

{# 列表分组,每组是一个子列表,组名就是分组项的值 #}

{% for group in users|groupby('gender') %}

{{ group.grouper }}

{% for user in group.list %}

{{ user.name }}

{% endfor %}

{% endfor %}

{# 取字典中的某一项组成列表,再将其连接起来 #}

{{ users | map(attribute='name') | join(', ') }}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

{%setusers=[{'name':'Tom','gender':'M','age':20},

{'name':'John','gender':'M','age':18},

{'name':'Mary','gender':'F','age':24},

{'name':'Bob','gender':'M','age':31},

{'name':'Lisa','gender':'F','age':19}]

%}

{# 按指定字段排序,这里设reverse为true使其按降序排 #}

{%foruserinusers|sort(attribute='age',reverse=true)%}

{{user.name}},{{user.age}}

{%endfor%}

{# 列表分组,每组是一个子列表,组名就是分组项的值 #}

{%forgroupinusers|groupby('gender')%}

{{group.grouper}}

{%foruseringroup.list%}

{{user.name}}

{%endfor%}

{%endfor%}

{# 取字典中的某一项组成列表,再将其连接起来 #}

{{users|map(attribute='name')|join(', ')}}

更全的内置过滤器介绍可以从Jinja2的官方文档中找到。

Flask内置过滤器

Flask提供了一个内置过滤器”tojson”,它的作用是将变量输出为JSON字符串。这个在配合Javascript使用时非常有用。我们延用上节字典列表操作中定义的”users”变量

var users = {{ users | tojson | safe }};

console.log(users[0].name);

1

2

3

4

varusers={{users|tojson|safe}};

console.log(users[0].name);

注意,这里要避免HTML自动转义,所以加上safe过滤器。

语句块过滤

Jinja2还可以对整块的语句使用过滤器。

{% filter upper %}

This is a Flask Jinja2 introduction.

{% endfilter %}

1

2

3

{%filterupper%}

ThisisaFlaskJinja2introduction.

{%endfilter%}

不过上述这种场景不经常用到。

自定义过滤器

内置的过滤器不满足需求怎么办?自己写呗。过滤器说白了就是一个函数嘛,我们马上就来写一个。回到Flask应用代码中:

def double_step_filter(l):

return l[::2]

1

2

defdouble_step_filter(l):

returnl[::2]

我们定义了一个”double_step_filter”函数,返回输入列表的偶数位元素(第0位,第2位,..)。怎么把它加到模板中当过滤器用呢?Flask应用对象提供了”add_template_filter”方法来帮我们实现。我们加入下面的代码:

app.add_template_filter(double_step_filter, 'double_step')

1

app.add_template_filter(double_step_filter,'double_step')

函数的第一个参数是过滤器函数,第二个参数是过滤器名称。然后,我们就可以愉快地在模板中使用这个叫”double_step”的过滤器了:

{# 返回[1,3,5] #}

{{ [1,2,3,4,5] | double_step }}

1

2

{# 返回[1,3,5] #}

{{[1,2,3,4,5]|double_step}}

Flask还提供了添加过滤器的装饰器”template_filter”,使用起来更简单。下面的代码就添加了一个取子列表的过滤器。装饰器的参数定义了该过滤器的名称”sub”。

@app.template_filter('sub')

def sub(l, start, end):

return l[start:end]

1

2

3

@app.template_filter('sub')

defsub(l,start,end):

returnl[start:end]

我们在模板中可以这样使用它:

{# 返回[2,3,4] #}

{{ [1,2,3,4,5] | sub(1,4) }}

1

2

{# 返回[2,3,4] #}

{{[1,2,3,4,5]|sub(1,4)}}

Flask添加过滤器的方法实际上是封装了对Jinja2环境变量的操作。上述添加”sub”过滤器的方法,等同于下面的代码。

app.jinja_env.filters['sub'] = sub

1

app.jinja_env.filters['sub']=sub

我们在Flask应用中,不建议直接访问Jinja2的环境变量。如果离开Flask环境直接使用Jinja2的话,就可以通过”jinja2.Environment”来获取环境变量,并添加过滤器。

完整代码如下:

from flask import Flask,render_template

app = Flask(__name__)

@app.route('/hello')

@app.route('/hello/')

def hello(name=None):

return render_template('hello-3.html', name=name)

########## Add Filter ##########

def double_step_filter(l):

return l[::2]

app.add_template_filter(double_step_filter, 'double_step')

@app.template_filter('sub')

def sub(l, start, end):

return l[start:end]

#app.jinja_env.filters['sub'] = sub

if __name__ == '__main__':

app.run(host='0.0.0.0', debug=True)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

fromflaskimportFlask,render_template

app=Flask(__name__)

@app.route('/hello')

@app.route('/hello/')

defhello(name=None):

returnrender_template('hello-3.html',name=name)

########## Add Filter ##########

defdouble_step_filter(l):

returnl[::2]

app.add_template_filter(double_step_filter,'double_step')

@app.template_filter('sub')

defsub(l,start,end):

returnl[start:end]

#app.jinja_env.filters['sub'] = sub

if__name__=='__main__':

app.run(host='0.0.0.0',debug=True)

Hello Sample

{% if name %}

Hello {{ name | upper | truncate(3, True) }}!

{% else %}

Hello World!

{% endif %}

{# 字符串操作 #}

{# 当变量未定义时,显示默认字符串 #}

{{ name | default('No name', true) }}

{# 单词首字母大写 #}

{{ 'hello' | capitalize }}

{# 单词全小写 #}

{{ 'XML' | lower }}

{# 去除字符串前后的空白字符 #}

{{ ' hello ' | trim }}

{# 字符串反转,返回"olleh" #}

{{ 'hello' | reverse }}

{# 格式化输出,返回"Number is 2" #}

{{ '%s is %d' | format("Number", 2) }}

{# 关闭HTML自动转义 #}

{{ 'name' | safe }}

{% autoescape false %}

{# HTML转义,即使autoescape关了也转义 #}

{{ 'name' | escape }}

{% endautoescape %}

{# 数值操作 #}

{# 四舍五入取整,返回13.0 #}

{{ 12.8888 | round }}

{# 向下截取到小数点后2位,返回12.88 #}

{{ 12.8888 | round(2, 'floor') }}

{# 绝对值,返回12 #}

{{ -12 | abs }}

{# 列表操作 #}

{# 取第一个元素 #}

{{ [1,2,3,4,5] | first }}

{# 取最后一个元素 #}

{{ [1,2,3,4,5] | last }}

{# 返回列表长度 #}

{{ [1,2,3,4,5] | length }}

{# 列表求和 #}

{{ [1,2,3,4,5] | sum }}

{# 列表排序,默认为升序 #}

{{ [3,2,1,5,4] | sort }}

{# 合并为字符串,返回"1 | 2 | 3 | 4 | 5" #}

{{ [1,2,3,4,5] | join(' | ') }}

{# 列表中所有元素都全大写。这里可以用upper,lower,但capitalize无效 #}

{{ ['tom','bob','ada'] | upper }}

{# 字典列表操作 #}

{% set users=[{'name':'Tom','gender':'M','age':20},

{'name':'John','gender':'M','age':18},

{'name':'Mary','gender':'F','age':24},

{'name':'Bob','gender':'M','age':31},

{'name':'Lisa','gender':'F','age':19}]

%}

{# 按指定字段排序,这里设reverse为true使其按降序排 #}

{% for user in users | sort(attribute='age', reverse=true) %}

{{ user.name }}, {{ user.age }}

{% endfor %}

{# 列表分组,每组是一个子列表,组名就是分组项的值 #}

{% for group in users|groupby('gender') %}

{{ group.grouper }}

{% for user in group.list %}

{{ user.name }}

{% endfor %}

{% endfor %}

{# 取字典中的某一项组成列表,再将其连接起来 #}

{{ users | map(attribute='name') | join(', ') }}

{# tojson #}

var users = {{ users | tojson | safe }};

console.log(users[0].name);

{% filter upper %}

This is a Flask Jinja2 introduction.

{% endfilter %}

{# 自定义过滤器 #}

{# 返回[1,3,5] #}

{{ [1,2,3,4,5] | double_step }}

{# 返回[2,3,4] #}

{{ [1,2,3,4,5] | sub(1,4) }}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

HelloSample

{%ifname%}

Hello{{name|upper|truncate(3,True)}}!

{%else%}

HelloWorld!

{%endif%}

{# 字符串操作 #}

{# 当变量未定义时,显示默认字符串 #}

{{name|default('No name',true)}}

{# 单词首字母大写 #}

{{'hello'|capitalize}}

{# 单词全小写 #}

{{'XML'|lower}}

{# 去除字符串前后的空白字符 #}

{{'  hello  '|trim}}

{# 字符串反转,返回"olleh" #}

{{'hello'|reverse}}

{# 格式化输出,返回"Number is 2" #}

{{'%s is %d'|format("Number",2)}}

{# 关闭HTML自动转义 #}

{{'name'|safe}}

{%autoescapefalse%}

{# HTML转义,即使autoescape关了也转义 #}

{{'name'|escape}}

{%endautoescape%}

{# 数值操作 #}

{# 四舍五入取整,返回13.0 #}

{{12.8888|round}}

{# 向下截取到小数点后2位,返回12.88 #}

{{12.8888|round(2,'floor')}}

{# 绝对值,返回12 #}

{{-12|abs}}

{# 列表操作 #}

{# 取第一个元素 #}

{{[1,2,3,4,5]|first}}

{# 取最后一个元素 #}

{{[1,2,3,4,5]|last}}

{# 返回列表长度 #}

{{[1,2,3,4,5]|length}}

{# 列表求和 #}

{{[1,2,3,4,5]|sum}}

{# 列表排序,默认为升序 #}

{{[3,2,1,5,4]|sort}}

{# 合并为字符串,返回"1 | 2 | 3 | 4 | 5" #}

{{[1,2,3,4,5]|join(' | ')}}

{# 列表中所有元素都全大写。这里可以用upper,lower,但capitalize无效 #}

{{['tom','bob','ada']|upper}}

{# 字典列表操作 #}

{%setusers=[{'name':'Tom','gender':'M','age':20},

{'name':'John','gender':'M','age':18},

{'name':'Mary','gender':'F','age':24},

{'name':'Bob','gender':'M','age':31},

{'name':'Lisa','gender':'F','age':19}]

%}

{# 按指定字段排序,这里设reverse为true使其按降序排 #}

{%foruserinusers|sort(attribute='age',reverse=true)%}

{{user.name}},{{user.age}}

{%endfor%}

{# 列表分组,每组是一个子列表,组名就是分组项的值 #}

{%forgroupinusers|groupby('gender')%}

{{group.grouper}}

{%foruseringroup.list%}

{{user.name}}

{%endfor%}

{%endfor%}

{# 取字典中的某一项组成列表,再将其连接起来 #}

{{users|map(attribute='name')|join(', ')}}

{# tojson #}

varusers={{users|tojson|safe}};

console.log(users[0].name);

{%filterupper%}

ThisisaFlaskJinja2introduction.

{%endfilter%}

{# 自定义过滤器 #}

{# 返回[1,3,5] #}

{{[1,2,3,4,5]|double_step}}

{# 返回[2,3,4] #}

{{[1,2,3,4,5]|sub(1,4)}}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值