python 模板函数_Flask的Jinja2模板引擎 — 全局函数(5th)

Jinja2模板引擎的另一个辅助函数功能,即全局函数Global Functions。如果说过滤器是一个变量转换函数,测试器是一个返回布尔值的函数,那全局函数就可以是任意函数。可以在任一场景使用,没有输入和输出值的限制。本篇我们就来阐述下这个全局函数。

全局函数使用

还是取出第一篇开篇的代码,我们在模板中加入下面的代码:

{% for num in range(10, 20, 2) %}

Number is "{{ num }}"

{% endfor %}

1

2

3

4

5

{%fornuminrange(10,20,2)%}

Numberis"{{ num }}"

{%endfor%}

页面上会显示”10,12,14,16,18″5个列表项。全局函数”range()”的作用同Python里的一样,返回指定范围内的数值序列。三个参数分别是开始值,结束值(不包含),间隔。如果只传两个参数,那间隔默认为1;如果只传1个参数,那开始值默认为0。

由此可见,全局函数如同其名字一样,就是全局范围内可以被使用的函数。其同第二篇介绍的上下文环境中定义的函数不同,没有请求生命周期的限制。

内置全局函数

演示几个常用的内置全局函数。

dict()函数,方便生成字典型变量

{% set user = dict(name='Mike',age=15) %}

{{ user | tojson | safe }}

{# 显示 '{"age": 15, "name": "Mike"}' #}

1

2

3

4

{%setuser=dict(name='Mike',age=15)%}

{{user|tojson|safe}}

{# 显示 '{"age": 15, "name": "Mike"}' #}

joiner()函数,神奇的辅助函数。它可以初始化为一个分隔符,然后第一次调用时返回空字符串,以后再调用则返回分隔符。对分隔循环中的内容很有帮助

{% set sep = joiner("|") %}

{% for val in range(5) %}

{{ sep() }} {{ val }}

{% endfor %}

{# 显示 "0 | 1 | 2 | 3 | 4" #}

1

2

3

4

5

6

{%setsep=joiner("|")%}

{%forvalinrange(5)%}

{{sep()}}{{val}}

{%endfor%}

{# 显示 "0 | 1 | 2 | 3 | 4" #}

cycler()函数,作用同第一篇介绍的循环内置变量”loop.cycle”类似,在给定的序列中轮循

{% set cycle = cycler('odd', 'even') %}

{% for num in range(10, 20, 2) %}

Number is "{{ num }}",

next line is "{{ cycle.current }}" line.

{% endfor %}

1

2

3

4

5

6

7

{%setcycle=cycler('odd','even')%}

{%fornuminrange(10,20,2)%}

Numberis"{{ num }}",

nextlineis"{{ cycle.current }}"line.

{%endfor%}

基于上一节的例子,加上”cycler()”函数的使用,你会发现列表项

的”class”在”odd”和”even”两个值间轮循。加入第一篇中的CSS style,就可以看到斑马线了。

“cycler()”函数返回的对象可以做如下操作

next(),返回当前值,并往下一个值轮循

reset(),重置为第一个值

current,当前轮循到的值

更全的内置全局函数介绍可以从Jinja2的官方文档中找到。

自定义全局函数

我们当然也可以写自己的全局函数,方法同之前介绍的过滤器啦,测试器啦都很类似。就是将Flask应用代码中定义的函数,通过”add_template_global”将其传入模板即可:

import re

def accept_pattern(pattern_str):

pattern = re.compile(pattern_str, re.S)

def search(content):

return pattern.findall(content)

return dict(search=search, current_pattern=pattern_str)

app.add_template_global(accept_pattern, 'accept_pattern')

1

2

3

4

5

6

7

8

9

importre

defaccept_pattern(pattern_str):

pattern=re.compile(pattern_str,re.S)

defsearch(content):

returnpattern.findall(content)

returndict(search=search,current_pattern=pattern_str)

app.add_template_global(accept_pattern,'accept_pattern')

上例中的accept_pattern函数会先预编译一个正则,然后返回的字典中包含一个查询函数”search”,之后调用”search”函数就可以用编译好的正则来搜索内容了。”app.add_template_global”方法的第一个参数是自定义的全局函数,第二个是全局函数名称。现在,让我们在模板中使用”accept_pattern”全局函数:

{% with pattern = accept_pattern("

(.*?)") %}

{% set founds = pattern.search("

TomBob") %}

{% for item in founds %}

Found: {{ item }}

{% endfor %}

Current Pattern: {{ pattern.current_pattern }}

{% endwith %}

1

2

3

4

5

6

7

8

9

{%withpattern=accept_pattern("

(.*?)")%}

{%setfounds=pattern.search("

TomBob")%}

{%foriteminfounds%}

Found:{{item}}

{%endfor%}

CurrentPattern:{{pattern.current_pattern}}

{%endwith%}

“Tom”和”Bob”被抽取出来了,很牛掰的样子。你还可以根据需要在”accept_pattern”的返回字典里定义更多的方法。

Flask同样提供了添加全局函数的装饰器”template_global”,以方便全局函数的添加。我们来用它将第二篇中取系统当前时间的函数”current_time”定义为全局函数。

import time

@app.template_global('end_with')

def current_time(timeFormat="%b %d, %Y - %H:%M:%S"):

return time.strftime(timeFormat)

1

2

3

4

importtime

@app.template_global('end_with')

defcurrent_time(timeFormat="%b %d, %Y - %H:%M:%S"):

returntime.strftime(timeFormat)

同第二篇中的一样,我们在模板中可以这样使用它:

Current Time is: {{ current_time() }}

Current Day is: {{ current_time("%Y-%m-%d") }}

1

2

CurrentTimeis:{{current_time()}}

CurrentDayis:{{current_time("%Y-%m-%d")}}

Flask添加全局函数的方法是封装了对Jinja2环境变量的操作。上述添加”current_time”全局函数的方法,等同于下面的代码。

app.jinja_env.globals['current_time'] = current_time

1

app.jinja_env.globals['current_time']=current_time

我们在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-5.html', name=name)

########## Add Global Functions ##########

import time

@app.template_global('current_time')

def current_time(timeFormat="%b %d, %Y - %H:%M:%S"):

return time.strftime(timeFormat)

import re

def accept_pattern(pattern_str):

pattern = re.compile(pattern_str, re.S)

def search(content):

return pattern.findall(content)

return dict(search=search, current_pattern=pattern_str)

app.add_template_global(accept_pattern, 'accept_pattern')

#app.jinja_env.globals['current_time'] = current_time

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

23

24

25

26

27

28

29

fromflaskimportFlask,render_template

app=Flask(__name__)

@app.route('/hello')

@app.route('/hello/')

defhello(name=None):

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

########## Add Global Functions ##########

importtime

@app.template_global('current_time')

defcurrent_time(timeFormat="%b %d, %Y - %H:%M:%S"):

returntime.strftime(timeFormat)

importre

defaccept_pattern(pattern_str):

pattern=re.compile(pattern_str,re.S)

defsearch(content):

returnpattern.findall(content)

returndict(search=search,current_pattern=pattern_str)

app.add_template_global(accept_pattern,'accept_pattern')

#app.jinja_env.globals['current_time'] = current_time

if__name__=='__main__':

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

Hello Sample

.odd {

background-color: #BDF;

}

{% if name %}

Hello {{ name }}!

{% else %}

Hello World!

{% endif %}

{% set cycle = cycler('odd', 'even') %}

{% for num in range(10, 20, 2) %}

Number is "{{ num }}",

next line is "{{ cycle.current }}" line.

{% endfor %}

{% set user = dict(name='Mike',age=15) %}

{{ user | tojson | safe }}

{# 显示 '{"age": 15, "name": "Mike"}' #}

{% set sep = joiner("|") %}

{% for val in range(5) %}

{{ sep() }} {{ val }}

{% endfor %}

{# 显示 "0 | 1 | 2 | 3 | 4" #}

Current Time is: {{ current_time() }}

Current Day is: {{ current_time("%Y-%m-%d") }}

{% with pattern = accept_pattern("

(.*?)") %}

{% set founds = pattern.search("

TomBob") %}

{% for item in founds %}

Found: {{ item }}

{% endfor %}

Current Pattern: {{ pattern.current_pattern }}

{% endwith %}

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

HelloSample

.odd{

background-color:#BDF;

}

{%ifname%}

Hello{{name}}!

{%else%}

HelloWorld!

{%endif%}

{%setcycle=cycler('odd','even')%}

{%fornuminrange(10,20,2)%}

Numberis"{{ num }}",

nextlineis"{{ cycle.current }}"line.

{%endfor%}

{%setuser=dict(name='Mike',age=15)%}

{{user|tojson|safe}}

{# 显示 '{"age": 15, "name": "Mike"}' #}

{%setsep=joiner("|")%}

{%forvalinrange(5)%}

{{sep()}}{{val}}

{%endfor%}

{# 显示 "0 | 1 | 2 | 3 | 4" #}

CurrentTimeis:{{current_time()}}

CurrentDayis:{{current_time("%Y-%m-%d")}}

{%withpattern=accept_pattern("

(.*?)")%}

{%setfounds=pattern.search("

TomBob")%}

{%foriteminfounds%}

Found:{{item}}

{%endfor%}

CurrentPattern:{{pattern.current_pattern}}

{%endwith%}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值