Flask过滤器分为两种,模板过滤器和自定义过滤器
顾名思义,模板过滤器是人家已经定义好的,你直接拿来使用就好了
自定义过滤器就是被人定义的你用不顺手,或者满足不了你的需求
那就自己造一个过滤器
在此之前有必要了解一下什么是过滤器?
过滤器是通过|进行使用的,它是一种特殊的占位符,告诉模板引擎这个位置的值从渲染模板时使用的数据中获取.
例如{{ name|length }},将返回name的长度,过滤器相当于是一个函数,把当前的的变量传入到过滤器中,
然后过滤器根据自己的功能,再返回相应的值,之后再渲染到模板页面中。
Jinja2能识别所有类型的变量,甚至是一些复杂的数据类型.
例如字典,列表,对象等.
<p>从字典去取一个值:{{ mydict['key'] }}}</p> <p>从列表去取一个值:{{ mylist[1] }}}</p> <p>从列表去取一个带索引的值:{{ mylist['name'] }}}</p> <p>从对象方法中取一个值:{{ myobj.method() }}}</p>
接下来我们先看看Flask常用的一些内置过滤器
字符串操作
{# 当变量未定义时,显示默认字符串,可以缩写为d #} <p>{{ name | default('No name', true) }}</p> {# 单词首字母大写 #} <p>{{ 'hello' | capitalize }}</p> {# 单词全小写 #} <p>{{ 'XML' | lower }}</p> {# 去除字符串前后的空白字符 #} <p>{{ ' hello ' | trim }}</p> {# 字符串反转,返回"olleh" #} <p>{{ 'hello' | reverse }}</p> {# 格式化输出,返回"Number is 2" #} <p>{{ '%s is %d' | format("Number", 2) }}</p> {# 关闭HTML自动转义 #} <p>{{ '<em>name</em>' | safe }}</p> {% autoescape false %} {# HTML转义,即使autoescape关了也转义,可以缩写为e #} <p>{{ '<em>name</em>' | escape }}</p> {% endautoescape %}
数值操作
{# 四舍五入取整,返回13.0 #} <p>{{ 12.8888 | round }}</p> {# 向下截取到小数点后2位,返回12.88 #} <p>{{ 12.8888 | round(2, 'floor') }}</p> {# 绝对值,返回12 #} <p>{{ -12 | abs }}</p>
列表操作
{# 取第一个元素 #} <p>{{ [1,2,3,4,5] | first }}</p> {# 取最后一个元素 #} <p>{{ [1,2,3,4,5] | last }}</p> {# 返回列表长度,可以写为count #} <p>{{ [1,2,3,4,5] | length }}</p> {# 列表求和 #} <p>{{ [1,2,3,4,5] | sum }}</p> {# 列表排序,默认为升序 #} <p>{{ [3,2,1,5,4] | sort }}</p> {# 合并为字符串,返回"1 | 2 | 3 | 4 | 5" #} <p>{{ [1,2,3,4,5] | join(' | ') }}</p> {# 列表中所有元素都全大写。这里可以用upper,lower,但capitalize无效 #} <p>{{ ['tom','bob','ada'] | upper }}</p>
字典列表操作
{% 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使其按降序排 #} <ul> {% for user in users | sort(attribute='age', reverse=true) %} <li>{{ user.name }}, {{ user.age }}</li> {% endfor %} </ul> {# 列表分组,每组是一个子列表,组名就是分组项的值 #} <ul> {% for group in users|groupby('gender') %} <li>{{ group.grouper }}<ul> {% for user in group.list %} <li>{{ user.name }}</li> {% endfor %}</ul></li> {% endfor %} </ul> {# 取字典中的某一项组成列表,再将其连接起来 #} <p>{{ users | map(attribute='name') | join(', ') }}</p>
介绍了这么多的过滤器我们用实例来看看如何使用
为了让页面更加好看,我们去Bootstrap上面扒一个页面
然后按照我们的需求改一下页面内容如下:
大概就这样了
而负责展示的HTML两个参数设置是这样的
我们在python函数中是这样定义这两个参数的
现在我们就来测试一下Flask其中一个过滤器
# 如果当前变量没有值,则会使用参数中的值来代替。 default(value,default_value,boolean=False):
这个过滤器是什么意思呢?
简单点来说就是有值显示值,没值显示default(就是你设置的默认值)
我们就来测试一下name
现在的值是demacia(德玛西亚)
我们现在将它设置为空
如果不出意料的话,他会打印出
'此地很懒,自己叫什么都不知道!'
再来看一组例子
我们把message信息换成一个无序的列表
[88, 99, 77, 22, 44, 66, 56, 13, 72, 27]
然后我们使用sort来对其进行排序
length求长度
这里只是列出了比较常用的过滤器,更多的过滤器可以查看官方文档http://jinja.pocoo.org/docs/2.10/templates/#list-of-builtin-filters
自定义过滤器
内置过滤器并不是都能满足人人需求,所有Jinja2还支持自定义过滤器.
一般创建自定义过滤器有两种方式
第一种是通过Flask应用对象的add_template_filter()方法
Flask应用对象add_template_filter()方法定义过滤器主要用于统计文字长度.
我们先创建一个run.py文件定义一个count_length()的函数,用于统计问名字长度
from flask import Flask, render_template # 求长度的函数 def count_length(parm): return len(parm) # 实例化Flask对象 app = Flask(__name__) # 添加函数 app.add_template_filter(count_length, 'count_length') @app.route('/') def index(): content = ''' 德玛西亚是一个法理至上的强大王国,战功赫赫,久负盛名。德玛西亚人自古崇尚正义、荣耀和责任,近乎狂热地以自身的传统及底蕴为豪。然而,尽管秉持着这些高尚的原则,在过去的几百年间,刚愎自用的德玛西亚越发与世隔绝,成为了孤立主义的代名词。 然而现在,王国中已经出现了变数。 德玛西亚雄都以禁魔石——一种可以抑制魔法能量的白色岩石——为基,起初是符文战争之后为了躲避魔法侵害的人们所建立的庇护地。王权由中心向外辐射,守护着边远的城镇、农田、森林和矿产丰饶的山脉。 然而,自从嘉文三世国王突然驾崩,各大家族至今仍未赞同他唯一的继承人嘉文王子继位。 在王国眼中,重兵把守的边境之外已经是异心遍起,许多原先的附庸在乱世来临之际开始寻求来自别处的庇护。有人私下妄言,德玛西亚的黄金时代已经一去不返,除非臣民能够上下一心,顺应时代的变化——许多人认为他们并没有这样的能力,否则王国的衰败在所难免。 再多的禁魔石,也无法阻止德玛西亚由内而外的覆灭 ''' return render_template('index.html', content =content) if __name__ == '__main__': app.run( debug=True, port=8000 )
然后将count_length()函数添加到add_template_filter()方法中作为过滤器使用.
<!DOCTYPE html> <html lang="en"> <body> <div> 全文共计{{ content|count_length }}字 </div> <p>{{ content }}</p> </body> </html>
接下我们去访问 http://127.0.0.1:8000/
第二种是通过app.template_filter()装饰器来实现自定义过滤器
创建run.py文件,在该文件中定义count_length()函数,用于统计文章字数
然后使用@app.template_filter装饰器修饰count_length()函数.
from flask import Flask, render_template # 实例化Flask对象 app = Flask(__name__) # 求长度的函数 @app.template_filter() def count_length(parm): return len(parm) @app.route('/') def index(): content = ''' 诺克萨斯是一个威名震天的强大帝国。在诺克萨斯境外的人眼中,它拥兵自重、血腥野蛮、欲壑难填,但对于那些看透它好战外表的人来说,这里的社会氛围实际上超乎寻常地包容。人民的所有特长和天赋都会得到尊重和受到培养的机会。 古代诺克西人是残暴的野蛮人部落联合,他们占领了一座古城,并将其建成了现在的帝国中心。当时的诺克萨斯面临着来自各方的威胁,所以他们与所有敌人都激烈交锋,睚眦必报,不胜不归,最终让帝国的版图连年扩张。这一段艰难求生的历史让诺克萨斯人从骨子里感到骄傲自豪,也因此重视力量胜过一切。当然,力量可以通过许多不同的形式表现。 无论社会立场、身世背景、祖国故乡和个人财富如何,任何人都可能在诺克萨斯获得权力、地位、和尊敬,只要他们能够表现出必要的能力。能够使用魔法的人会被高看一眼,帝国甚至会主动寻觅这类人,让他们的特殊天赋得到锻炼并最高效地为帝国所用。 虽然诺克萨斯有贤能统治的政治理想,但老一辈贵族家庭依然在帝国的心脏把持着相当大的权力,有人担心诺克萨斯最大的威胁并非来自敌人,而是来自内部 ''' return render_template('index.html', content =content) if __name__ == '__main__': app.run( debug=True, port=8000 )
效果与上面是一样的
控制效果
Jinja2中也提供了许多的控制结构,作用是为了改变模板的渲染流程。
{% %}是Jinja2中的控制语句, {{ }}是Jinja2中的变量, {# #}是注释。
那么模板中是如何使用条件控制语句呢?
条件控制结构
根据值,选择不同的语句执行 ,从而获得不同的响应字符串。
<!DOCTYPE html> <html lang="en"> <body> {% if name %} <h1>Hello {{ name }}, can you hear me !</h1> {% else %} <h1>Hello World!</h1> {% endif %} </body>
循环控制语句
<!DOCTYPE html> <html lang="en"> <body> <ul> {% for item in items %} <li>{{ item }}</li> {% endfor %} </ul> </body>
run.py文件
from flask import Flask, render_template # 实例化Flask对象 app = Flask(__name__) @app.route('/') def control(): name = '大魔王' my_list = list(range(1,10)) return render_template('index1.html', items = my_list) if __name__ == '__main__': app.run( debug=True, port=8000 )
好了,关于Flask模板我们专门拉出一节单讲是因为它足够重要,
下一节我们一起来看看Flask中的模板