Flask 入门教程:Jinja2模板用法
Posted 多鱼的夏天
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask 入门教程:Jinja2模板用法相关的知识,希望对你有一定的参考价值。
Jinja2模板引擎简介
模板
在前面的示例中,视图函数的主要作用是生成请求的响应,这是最简单的请求。实际上,视图函数有两个作用:处理业务逻辑和返回响应内容。在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本。本节学到的模板,它的作用即是承担视图函数的另一个作用,即返回响应内容。
- 模板其实是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取
- 使用真实值替换变量,再返回最终得到的字符串,这个过程称为“渲染”
- Flask是使用 Jinja2 这个模板引擎来渲染模板
使用模板的好处:
- 视图函数只负责业务逻辑和数据处理(业务逻辑方面)
- 而模板则取到视图函数的数据结果进行展示(视图展示方面)
- 代码结构清晰,耦合度低
渲染模版函数
- Flask提供的 render_template 函数封装了该模板引擎
- render_template 函数的第一个参数是模板的文件名,后面的参数都是键值对,表示模板中变量对应的真实值。
模版使用
来表示变量名,这种 语法叫做变量代码块
<h1> post.title </h1>
代码中传入字符串,列表,字典到模板中
@app.route('/')
def index():
name = '长弓'
data =
'key':'python讲师',
'array':[1,2,3,4,5],
'dicts':
'name':'老王',
'age':12
,
"info": [
'name': '王昭君',
'age': 18
,
'name': '小鲁班',
'age': 8
]
user = '貂蝉'
return render_template('index.html',name=name,data=data,user=user)
模板中代码
<!-- 普通取值 -->
<h1> name </h1>
<!-- 列表取值 -->
<p> data.array </p>
<p> data.array.0 </p>
<p> data.array[1] </p>
<!-- 字典取值 -->
<p> data.dicts </p>
<p> data.dicts['name'] </p>
<!-- 列表套字典取值 -->
<p> data.info </p>
<p> data.info.0 </p>
<p> data.info[1] </p>
访问:http://127.0.0.1:5000/ 运行测试
Flask过滤器
过滤器的本质就是函数。有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化、运算等等,而在模板中是不能直接调用 Python 中的某些方法,那么这就用到了过滤器。
使用方式:
- 过滤器的使用方式为:变量名 | 过滤器。
variable | filter(*args)
- 如果没有任何参数传给过滤器,则可以把括号省略掉
variable | filter
- 如:``,这个过滤器的作用:把变量variable 的值的首字母转换为大写,其他字母转换为小写
常见内置过滤器
<!-- 字符串转大写 -->
<p> "hello" | upper </p>
<!-- 首字母大写 -->
<p> "hello"| capitalize </p>
<!-- 字符串反转 -->
<p> "hello" | reverse </p>
<p> [1,2,3,4,5,6] | sum </p>
<p> [1,2,3,4,5,6] | length </p>
<p> [1,2,3,4,5,6] | last </p>
<p> [6,2,3,1,5,4] | sort </p>
链式调用
在 jinja2 中,过滤器是可以支持链式调用的,示例如下:
"hello world" | reverse | upper
自定义过滤器
过滤器的本质是函数。当模板内置的过滤器不能满足需求,可以自定义过滤器。自定义过滤器有两种实现方式:
- 一种是通过Flask应用对象的 add_template_filter 方法
- 通过装饰器来实现自定义过滤器
重要:自定义的过滤器名称如果和内置的过滤器重名,会覆盖内置的过滤器。
用装饰器来实现自定义过滤器。装饰器传入的参数是自定义的过滤器名称。
@app.template_filter('lireverse')
def do_listreverse(li):
# 通过原列表创建一个新列表
temp_li = list(li)
# 将新列表进行返转
temp_li.reverse()
return temp_li
-
在 html 中使用该自定义过滤器
<!-- 自定义过滤器 --> <p> [6,2,3,1,5,4] | lireverse </p>
控制流程
控制代码块主要包含两个:
- if/else if /else / endif
- for / endfor
条件控制
Jinja2 语法中的if语句跟 Python 中的 if 语句相似,后面的布尔值或返回布尔值的表达式将决定代码中的哪个流程会被执行:
<!-- 控制代码块 -->
% if user == '貂蝉a' %
<p> 吕布 </p>
% else %
<p> 董卓 </p>
% endif %
循环控制
% for post in data.info %
<div>
<h1> post.name</h1>
<h1> post.age</h1>
</div>
% endfor %
-
在一个 for 循环块中你可以访问这些特殊的变量:
变量 描述 loop.index 当前循环迭代的次数(从 1 开始) loop.index0 当前循环迭代的次数(从 0 开始) loop.revindex 到循环结束需要迭代的次数(从 1 开始) loop.revindex0 到循环结束需要迭代的次数(从 0 开始) loop.first 如果是第一次迭代,为 True 。 loop.last 如果是最后一次迭代,为 True 。 loop.length 序列中的项目数。 loop.cycle 在一串序列间期取值的辅助函数。见下面示例程序。
在循环内部,你可以使用一个叫做loop的特殊变量来获得关于for循环的一些信息
- 比如:要是我们想知道当前被迭代的元素序号,并模拟Python中的enumerate函数做的事情,则可以使用loop变量的index属性,例如:
% for post in data.info %
<div>
<h1> loop.index </h1>
<h1> post.name</h1>
<h1> post.age</h1>
</div>
% endfor %
模版变量域
set语句:
在模版中,可以使用set
语句来定义变量。示例如下:
% set username='路慢慢其修远兮' %
<p>座右铭: username </p>
<span>座右铭: username </span>
一旦定义了这个变量,那么在后面的代码中,都可以使用这个变量,就类似于Python的变量定义是一样的。
with语句:
with
语句定义的变量,只能在with
语句块中使用,超过了这个代码块,就不能再使用了。示例代码如下:
% with sex = '女' %
<p>性别: sex </p>
% endwith %
<!-- 失效 -->
<p>性别: sex </p>
模板复用
在模板中,可能会遇到以下情况:
- 多个模板具有完全相同的顶部和底部内容
- 多个模板中具有相同的模板代码内容,但是内容中部分值不一样
- 多个模板中具有完全相同的 html 代码块内容
像遇到这种情况,可以使用 JinJa2 模板中的 宏、继承、包含来进行实现
宏
- 把它看作 Jinja2 中的一个函数,它会返回一个模板或者 HTML 字符串
- 为了避免反复地编写同样的模板代码,出现代码冗余,可以把他们写成函数以进行重用
- 需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免重复
定义宏
% macro input(name, value='' ,type='text') %
<input type="type" name="name"
value=" value " class="form-control">
% endmacro %
使用宏
input ('长弓' , value='cg')
input ('username' , value='貂蝉')
输出效果
<input type="text" name="长弓"
value="cg" class="form-control">
<input type="text" name="username"
value="貂蝉" class="form-control">
案例:
使用宏之前的代码
<form>
<label>用户名:</label><input type="text" name="username"><br/>
<label>密码:</label><input type="password" name="password"><br/>
<label>确认密码:</label><input type="password" name="password2"><br/>
<label>手机号:</label><input type="text" name="phone"><br/>
<input type="submit" value="注册">
</form>
定义宏
% macro input(label="", type="text", name="", value="") %
<label> label </label><input type=" type " name=" name " value=" value ">
% endmacro %
使用宏
<form>
input("用户名:", name="username") <br/>
input("密码:", type="password", name="password") <br/>
input("确认密码:", type="password", name="password2") <br/>
input("手机号:", name="phone") <br/>
input(type="submit", value="注册")
</form>
继承
模板继承是为了重用模板中的公共内容。一般Web开发中,继承主要使用在网站的顶部菜单、底部。这些内容可以定义在父模板中,子模板直接继承,而不需要重复书写。
- 标签定义的内容
% block top % % endblock %
相当于在父模板中挖个坑,当子模板继承父模板时,可以进行填充。
子模板使用 extends 指令声明这个模板继承自哪个模板
父模板中定义的块在子模板中被重新定义,在子模板中调用父模板的内容可以使用super()
父模板
定义 base.html
% block top %
顶部菜单
% endblock top %
% block content %
% endblock content %
% block bottom %
底部
% endblock bottom %
子模板
extends指令声明这个模板继承自哪
% extends 'base.html' %
% block content %
需要填充的内容
% endblock content %
模板继承使用时注意点:
- 不支持多继承
- 为了便于阅读,在子模板中使用extends时,尽量写在模板的第一行。
- 不能在一个模板文件中定义多个相同名字的block标签。
- 当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。
包含
Jinja2模板中,除了宏和继承,还支持一种代码重用的功能,叫包含(Include)。它的功能是将另一个模板整个加载到当前模板中,并直接渲染。
- include的使用
% include 'common.html' %
包含在使用时,如果包含的模板文件不存在时,程序会抛出TemplateNotFound异常,可以加上 ignore missing
关键字。如果包含的模板文件不存在,会忽略这条include语句。
- include 的使用加上关键字ignore missing
% include 'common.html' ignore missing %
小结
- 宏(Macro)、继承(Block)、包含(include)均能实现代码的复用。
- 继承(Block)的本质是代码替换,一般用来实现多个页面中重复不变的区域。
- 宏(Macro)的功能类似函数,可以传入参数,需要定义、调用。
- 包含(include)是直接将目标模板文件整个渲染出来。
以上是关于Flask 入门教程:Jinja2模板用法的主要内容,如果未能解决你的问题,请参考以下文章
Flask第四篇 Flask 中的模板语言 Jinja2 及 render_template 的深度用法
Flask最强攻略 - 跟DragonFire学Flask - 第四篇 Flask 中的模板语言 Jinja2 及 render_template 的深度用法
3,Flask 中的模板语言 Jinja2 及 render_template 的深度用法
第四篇 Flask 中的模板语言 Jinja2 及 render_template 的深度用法