目录
(1)jinja2作用简介
- jinja2主要任务是实现html页面的渲染。在flask项目中,业务逻辑由视图函数来完成,而页面逻辑由jinja2渲染模板来完成。
- jinja2渲染模板通过接收来自视图函数的数据,生成html代码或其他前端框架的代码。
(2)jinja2渲染模板
1)Flask如何使用jinja2渲染模板
- Flask提供render_template()函数把jinja2模板引擎集成到应用中;默认情况下,Flask在templates目录里寻找模板。
- 所以jinja2模板应存放在templatesh目录中。
2)Flask使用jinja2模板案例
第一步:在templates目录建 index.html 与 user.html 两模板
index.html模板内宾
<h1>Hello World</h1>
user.html模板内容
<h1>Hello,{{name}}!</h1>
第二步:使用render_template()调用模板并传递输入数据
from flask import Flask,render_template
@app.route('/')
def index():
return render_template('index.html')
@app.route('/user/<name>')
def user(name):
return render_template('user.html',name=name)
#render_template()中第1个name 为 user.html模板中的name(模板中变量)
#第2个name 为 @app.route('/user/<name>') 中的name(传递给模板name变量的值)
3)Flask与模板相关的函数
flask.render_template()
引入模板并向模板传参数
flask.render_template_string()
# Renders a template from the given template source string with the given context.
flask.get_template_attribute(template_name, attribute)
# Loads a macro (or variable) a template exports. This can be used to invoke a macro from within Python code.
(3)jinja2变量与变量过滤器
1)定义变量
jinja2模板使用{{name}}表示变量。
jinja2能识别所有类型的变量,例如列表、字典、对象等,如下例:
- <p>A value from a dictionary: {{mydict['key']}} </p>
- <p>A value from a list: {{mylist[0]}} </p>
- <p>A value from a list,with a variable index: {{mylist[myvar]}} </p>
- <p>A value from an object's method:{{myobj.somemethod()}} </p>
2)变量过滤器
[1]字符串操作
- safe:禁用转义
- <p>{{ '<em>hello</em>' | safe }}</p>
- capitalize:把变量值的首字母转成大写,其余字母转小写
- lower:把值转成小写
- upper:把值转成大写
- title:把值中的每个单词的首字母都转成大写
- reverse:字符串反转
- <p>{{ 'olleh' | reverse }}</p>
- format:格式化输出
- <p>{{ '%s is %d' | format('name',17) }}</p>
- striptags:渲染之前把值中所有的HTML标签都删掉
- <p>{{ '<em>hello</em>' | striptags }}</p>
- truncate: 字符串截断
- <p>{{ 'hello every one' | truncate(9)}}</p>
[2]列表操作
- first:取第一个元素
- <p>{{ [1,2,3,4,5,6] | first }}</p>
- last:取最后一个元素
- <p>{{ [1,2,3,4,5,6] | last }}</p>
- length:获取列表长度
- <p>{{ [1,2,3,4,5,6] | length }}</p>
- sum:列表求和
- <p>{{ [1,2,3,4,5,6] | sum }}</p>
- sort:列表排序
- <p>{{ [6,2,3,1,5,4] | sort }}</p>
[3]语句块操作
- {% filter upper %} #一大堆文字# {% endfilter %}
(4)jinja2控制语句
1)if条件语句
{% if user == 'westos'%}
{% elif user == 'hello'%}
{% else %}
{% endif%}
例:
{% if user %}
hello ,{{user}}!
{% else %}
hello ,stranger!
{% endif %}
2)for循环语句
#语法案例
{% for i in li%}
{% endfor %}
#案例:迭代列表
<ul>
{% for user in users %}
<li>{{ user.username|title }}</li>
{% endfor %}
</ul>
#案例:迭代字典
<dl>
{% for key, value in my_dict.iteritems() %}
<dt>{{ key }}</dt>
<dd>{{ value}}</dd>
{% endfor %}
</dl>
3)for循环特殊变量
- 在for循环中,jinja2还提供了一些特殊的变量,用以来获取当前的遍历状态:
- loop.index 当前迭代的索引(从1开始)
- loop.index0 当前迭代的索引(从0开始)
- loop.first 是否是第一次迭代,返回bool
- loop.last 是否是最后一次迭代,返回bool
- loop.length 序列中的项目数量
- loop.revindex 到循环结束的次数(从1开始)
- loop.revindex0 到循环结束的次数(从0开始)
(5)jinja2宏操作
jinja2的宏与python中的函数类似,可以传递参数,但没有返回值
1)jinja2定义与调用宏
定义宏: {% macro 宏名称(参数) %} 宏内容 {% endmacro %}
调用宏: {{ 宏名称(参数) }}
案例1:定义宏带有参数默认值
{% macro input(name, value='', type='text') %}
<input type="{{ type }}" name="{{ name }}" value="{{value|e }}">
{% endmacro %}
案例2:在for循环中使用宏
{% macro render_comment(comment) %}
<li> {{comment}} </li>
{% endmacro %}
<ul>
{% for comment in comments %}
{{ render_comment(comment) }}
{% endfor %}
</ul>
2)jinja2导入宏
实际开发中,很少将宏在同一个页面定义并使用,一般都是放在指定的文件夹中,然后将宏的导入使用。
[1]import...as...
- {% import 'forms.html' as forms %}
- {% import "macros/macros.html" as macros %}
[2]from...import...as.../from...import...
- {% from 'forms.html' import input as input_field %}
- {% from "macros/macros.html" import input as inp %}
[3]with context
- 若导入宏时要把当前模版的一些参数传给宏所在的模版,应使用with context
- import "宏文件的路径" as xxx with context
- {% from '_helpers.html' import my_macro with context %}
(6)jinja2 block块
1)模板的继承
- 继承有两方面意义:不但继承父模板所有内容,还可以对继承过来的内容进行修改。
- 关于模板的继承,在子模板的顶部使用如"{% extend ‘base.html’ %}"语句来声明继承。
- 子模板中"{% block block_name %}"和"{% endblock %}"所包括的语句块,将会替换父模板中同样由"{% block block_name %}"和"{% endblock %}"所包括的语句块。
继承要注意以下两点:
- 模板不支持多继承,也就是子模板中定义的块,不可能同时替换两个父模板的块。
- 模板中不能定义同名的块,因为这样无法确认替换块的内容。
说明:
- 模板是作为 继承页面的底板,继承页面架构是在底板基础上进行修改
- 在继承页面中,重定义模板的block,将用新定义内容 覆盖 该block原定义的内容; 若不想保留原定义的内容,则使用 {{ super() }}
2)block内语句作用域
默认情况下,块内语句是无法访问块外作用域中的变量。比如:
{% for item in range(5) %}
<li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}
模板中定义”list”块并访问循环中的”item”变量:
这个例子会输出空的 < li> 项,因为 item 在块中是不可用的。
其原因是,如果 块被子模板替换,变量在其块中可能是未定义的或未被传递到上下文。
从 Jinja 2.2 开始可以显式地指定在块中可用的变量,只需在块声明中添加 scoped 修饰,就把块设定到作用域中:
{% for item in range(5) %}
<li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
{% endfor %}
3)super()保留父模板的块里的内容
base.html
{% block body %}
hello
{% endblock %}
#use_block.html
{% block body %}
{{ super() }} {# 加载父模板bas.html中 body块内容 #}
<span style="color: green">这是最新填的block内容</span>
{% endblock %}
(7)jinja2 include语句
1)include语句作用
- "{% include %}"语句,其功能就是将另一个模板加载到当前模板中,并直接渲染在当前位置上。
- 它同导入"import"不一样,"import"之后你还需要调用宏来渲染你的内容,"include"是直接将目标模板渲染出来。
- 它同block块继承也不一样,它一次渲染整个模板文件内容,不分块。
2)ignore missing
- {% include 'footer.html' ignore missing %}
- 加上"ignore missing",若模板不存在则会忽略这段"{% include %}"语句,否则程序会抛出异常。
3)include模板列表
- {% include ['footer.html','bottom.html','end.html'] ignore missing %}
- # 上例中,程序会按顺序寻找模板文件,第一个被找到的模板即被加载,而其后的模板都会被忽略。如果都没找到,那整个语句都会被忽略。