渲染模板
模板是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体值只在请求上下文才能知道。使用真实值
替换变量,再返回最终得到的响应字符串,这一过程称为渲染。为了渲染模板,Flask使用了一个Jinja2的模板引擎。
如下是一个简单的仅包含响应文本的文件:
<h1>Hello World!</h1>
如下是一个包含了变量的动态部分的响应文本的文件:
<h1>Hello, {{name}}!</h1>
在Jinja2模板中基本语句如下:
{{ ... }}
:装载一个变量,模板渲染的时候,会使用传进来的同名参数这个变量代表的值替换掉。{% ... %}
:装载一个控制语句。{# ... #}
:装载一个注释,模板渲染的时候会忽视这中间的值。
接下来需要让Flask程序能够找到并使用模板文件
因为在默认情况下,Flask程序会在templates子文件夹中寻找模板,故在新建项目(在这里我们新建项目hello.py)的同级目录下新建templates文件夹
然后在templates文件夹中新建index.html和user.html,并分别写入之前的模板示例
在上一次的编写代码中稍作修改以便程序渲染这些模板
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/user/<name>')
def user(name):
return render_template('user.html',name=name)
if __name__ == '__main__':
app.run()
Flask提供的render_template()函数把Jinja2模板引擎集成到了程序中。render_template()函数的第一个参数为文件名,随后的参数都是键对值,表示模板中变量对应的真实值。例如在这段代码中,第二个模板收到了名为name的变量,可以当作左边的“name”是模板中的占位符,右边的“name”是当前作用域中的变量,通过这样将真实值引入模板中。
运行hello.py程序,访问http://127.0.0.1:5000浏览器得到响应:
变量
Jinja2能识别所有类型的变量,甚至是一些复杂的类型,例如列表,字典和对象。在模板中使用变量的一些示例如下:
<p>a value from dictionary:{{ mydict['key'] }}</p>
<p>a value from list:{{ mylist[2] }}</p>
<p>a value from an object's method:{{ myobj.method() }}</p>
可以使用过滤器修改变量,过滤名添加在变量名之后,中间用竖线分开。常用过滤器如下:
过滤器 | 说明 |
---|---|
safe | 渲染值时不转义 |
capitalize | 把值的首字母转化为大写,其他字母转换为小写 |
lower | 把值转换为小写形式 |
upper | 把值转换为大写形式 |
title | 把值中每个单词的首字母都转换成大写形式 |
trim | 把值首位的空格去掉 |
striptags | 渲染之前把值中所有的HTML标签都删掉 |
#完整的过滤器列表可在Jinja2文档(http://jinja.pocoo.org/docs/templates/#builtin-filters)中查看
例如:将user.html内容改为:
<h1>Hello, {{ name|upper }}</h1>
这时再访问http://127.0.0.1:5000/user/Flask,浏览器将显示变量的全大写形式,即“Hello, FLASK”。
值得注意的是safe过滤器,在默认情况下,Jinja2会转义所有的变量。例如,一个变量的值为'<h1>Hello</h1>',Jinja2会将其渲染为 '<h1>Hello</h1gt; ' ,浏览器能显示h1元素但不会进行解释。很多情况下需要显示变量中存储的HTML代码,这时就可以使用safe过滤器。
控制结构
Jinja2中提供了多种控制结构,以下给出常用示例
在模板中使用条件控制语句:
{% if user %}
Hello, {{user}}!
{% else %}
Hello, Stranger!
{% endif %}
使用for循环渲染一组元素:
<ul>
{% for comment in comments %}
<li>{{ comment }}</li>
{% endfor %}
</ul>
Jinja2还支持宏,宏类似于Python中的函数。例如:
{% macro render_comment(comment) %}
<li>{{ comment }}</li>
{% endmacro %}
<ul>
{% for comment in comments %}
{{ render_comment(comment) }}
{% endfor %}
</ul>
在Jinja2中还可以将其保存在单独的文件中,在需要时进行导入,例如将上例中定义的宏保存为macros.html后:
{% import 'macros.html' as macros %}
<ul>
{% for comment in comments %}
{{macros.render_comment(comment)}}
{% endfor %}
</ul>
模板继承,类似于Python中的类继承。首先创建一个base.html的基模板:
<html>
<head>
{% block head %}
<title>{% block title %}{% endblock %}Flask</title>
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
block标签定义的元素可在衍生模板中修改。在本例中定义了名为head、title和body的块,下面是基模板的衍生模板:
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style>
</style>
{% endblock %}
{% block body %}
<h1>Hello, World!</h1>
{% endblock %}
entends指令声明这个模板衍生自base.html。在extends指令之后,基模板中的3个块被重新定义,模板引擎会将其插入到适当的位置。注意重新定义的head块,在基模板中其内容不是空的,所以使用super()获取原来的内容。