Flask是一款轻量级的用python实现的web微框架,它基于Werkzeug WSGI工具包和Jinja2模板引擎。
前面初步认识了Wekzeug这一个WSGI工具包,那么Jinja又有什么神通...
Jinja
Jinja是一个python编写的web模板引擎,作者是来自Pocoo的Armin Ronacher,首次发布于2008年7月17日,采用BSD协议授权,目前最新版本是3.1.2。
安装
安装很简单,注意加上2
。不然会遇到老版本的jinja。
不然前面安装了Flask,默认已经装上Jinja2,所以不用太考虑
JInja内容挺多,详见:https://jinja.palletsprojects.com/en/3.1.x/templates/
此处仅通过小例子做些基本了解
例子一
Jinja做的事情很简单,先给它一个包含占位符的模板(模板加载),再提供包含变量的上下文给它,让其完成变量替换(模板渲染)。注意,变量定义格式{{vvvvv}}
模板可以在字符串中:
| import jinja2
env = jinja2.Environment()
template = env.from_string('Hello {{ name }}!')
print(template.render(name='Debao'))
|
Jinja的核心组件时Environment这个类,此处构造时没有传入任何参数给它。
输出结果
这个例子,只完成字符串替换,实在没意思
例子二
模板一般都在文件中,文件名是什么后缀都无所谓。.htm,.latex,.txt,.jinja 都没关系。模板中的注释格式{# #}
比如,写一个模板:
| {# hello.txt for example #}
Hello {{ name }}!
|
然后渲染它:
| from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('hello.txt')
print(template.render(name='Debao'))
|
render
的参数,可以是关键字参数,也可以是dict。上面最后一行,可以改为:
| print(template.render({'name':'Debao'}))
|
例子三
只是变量替换意义不大,Jinja支持分支和循环等流程控制。
模板:
| {# hello.txt for example #}
Hello.txt file
{% for account in accounts %}
Name: {{ account.name }} Email: {{ account.email }}
{% endfor %}
|
渲染:
| from jinja2 import Environment, FileSystemLoader
accounts = [
{'name': 'Debao', 'email': 'd@example.com'},
{'name': 'Debao2', 'email': 'd2@example.com'},
]
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('hello.txt')
print(template.render({'accounts': accounts}))
|
注意:
- 变量可以是python任意对象
- for格式
{% for in %}
{% endfor %}
与此类似,if的格式如下:
| {% if score > 80 %}
I'm happy to inform you that you did very well on today's test.
{% else %}
I'm sorry to inform you that you did not do so well on today's test.
{% endif %}
|
另外,for 和 if 的语句彼此可以嵌套使用。
例子四
看看block,单纯加上它对结果没什么影响,比如:
| {# hello.txt for example #}
Hello.txt file
{% block content %}
{% for account in accounts %}
Name: {{ account.name }} Email: {{ account.email }}
{% endfor %}
{% endblock %}
|
但是,我们可以写另一个模板来覆盖对应的block:
| {# hello2.txt for example #}
{% extends "hello.txt" %}
{% block content %}
{% for account in accounts %}
New Name: {{ account.name }} Email: {{ account.email }}
{% endfor %}
{% endblock %}
|
注意其中的extends
。这样我们可以获取和渲染它了 env.get_template('hello2.txt')
除此之外,Jinja还有include
和import
等扩展机制
| {% include 'header.html' %}
Body goes here.
{% include 'footer.html' %}
|
- import 用于导入其他文件中的定义的宏macro
| {% import 'forms.html' as forms %}
|
Flask模板
回归正题,看看Jinja模板在Flask中如何使用。
Flask需要将 Jinja模板放置在 templates 文件夹下,以便于使用render_template()
进行渲染
这样(对应python模块):
| /hello.py
/templates
/hello.html
|
或者(对应python包)
| /hello
/__init__.py
/templates
hello.heml
|
例子
相比Jinja,这个就没多少新东西了...
1
2
3
4
5
6
7
8
9
10
11
12 | {# templates/base.html #}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
</head>
<body>
<h1>Welcome to {{ title }}!</h1>
</body>
</html>
|
| from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('base.html', title='Flask')
if __name__ == '__main__':
app.run('localhost', 8000)
|
参考
- https://flask.palletsprojects.com
- https://palletsprojects.com/p/jinja/
- https://jinja.palletsprojects.com/en/3.1.x/templates/
- https://en.wikipedia.org/wiki/Jinja_(template_engine)
- https://realpython.com/primer-on-jinja-templating/