Jinja2简介
Jinja 是一种快速的、富有表现力的、可扩展的模板引擎。模板中的特殊占位符允许编写类似于 Python 语法的代码,然后向模板传递数据来呈现出最终的文档。
特征
-
模板可以被继承或者被包含。 -
可以在模板中定义和导入宏(Macro,批量处理。根据一系列预定义的规则替换一定的文本模式)。
{% macro input(name, type='text', value='') -%}
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}">
{% endmacro %}
- 宏定义要加
macro ,结束时要用endmacro 。宏名称为input ,有三个参数type 、name 、value 。
<p>用户名:{{ input('username') }}</p>
<p>密码:{{ input('password', type='password') }}</p>
-
HTML 模板可以使用自动转义来防止 XSS 来自不信任的用户输入。
- XSS 攻击 - 跨站脚本攻击,攻击者恶意制造的网页程序。通常指利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行。
-
沙箱可以安全地呈现不受信任的模板。 -
AsyncIO(异步IO) 支持生成模板和调用异步函数。 -
I18N 支持 Babel。 -
模板即时编译为优化的 Python 代码并缓存,或者可以提前编译。 -
异常指向模板中的正确行以使调试更容易。 -
可扩展的过滤器、测试、函数、甚至语法。
Jinja的理念
如果可能的话,应用程序的逻辑属于 Python,但它不应该因为过多地限制功能而使得模板设计者的工作变得困难。
Jinja2使用
继承
模板文件 model.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body style="background-color: antiquewhite">
<h1>你好世界!</h1>
</body>
</html>
普通文件 index.html
{% extends 'model.html' %}
Python代码
@app.route('/index')
def index():
return render_template('index.html')
页面展示:
循环控制
Python代码
@app.route('/index')
def index():
users = [
{'name': '孙悟空'},
{'name': '赵云'},
{'name': '林黛玉'},
{'name': '武松'}
]
return render_template('index.html', users=users)
model.html
<body style="background-color: antiquewhite">
{% block content %}{% endblock %}
</body>
index.html
{% extends 'model.html' %}
{% block content %}
<div>
<ul>
{% for user in users %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
</div>
{% endblock %}
页面展示:
条件控制
Python代码
@app.route('/index')
def index():
num = 3
return render_template('index.html', num=num)
model.html 同循环。
index.html
{% extends 'model.html' %}
{% block content %}
<div>
<p>
{% if num > 10 %}
Hello World<br>
{% elif num < 10 %}
Hello Python<br>
{% else %}
GoodBye<br>
{% endif %}
</p>
</div>
{% endblock %}
页面展示
过滤器
过滤器,可以对变量进行修改。
过滤器通过管道符号 | 与变量分隔开,并且在括号中可以包含可选参数。
一个变量可以链接多个过滤器,下一个过滤器过滤的内容是基于上一个过滤器的输出。
常用过滤器
-
upper 大写字母 所有的英文字母都将会被转化为大写字母。 {{ 'hello'|upper }}
-
lower 小写字母 所有的英文字母都将会被转化为小写字母。 {{ 'HELLO'|lower }}
-
reverse 反转 所有字符反向输出。 {{ '你好!Python'|reverse }}
-
title 首字母大写。 每个独立的单词的首字母将会转化为大写。 {{ 'hello world'|title }}
备注: 如果是 helloworld 那么最终转化是 Helloworld 。 -
capitalize 首字母大写,其余的小写 将第一个单词的首字母转化为大写,其余部分的字母全部转化为小写。 {{ 'gOOD jOB! bOy'|capitalize }}
其他常用过滤器
- safe - 禁止转义,渲染时不会转义特殊字符。
- trim - 去掉首尾空格。
- striptags - 去掉所有的HTML标签。
- join - 将多个值拼接成字符串。
- replace - 替换字符串的值。
- round - 对数字进行四舍五入。
- int - 转换为 int 类型。
列表过滤器
-
获取列表的第一个元素 {{ list|first }}
-
获取列表的最后一个元素 {{ list|last }}
-
将列表以从小到大重新排序 {{ list|sort }}
-
求列表中所有值的总和 {{ list|sum }}
-
获取列表的长度 {{ list|length }}
Python代码
@app.route('/index')
def index():
list = [1, 3, 5, 2, 4, 6, 8, 7]
return render_template('index.html', list=list)
index.html
<div>
首位元素:{{ list|first }}<br>
末位元素:{{ list|last }}<br>
排序:{{ list|sort }}<br>
求和:{{ list|sum }}<br>
长度:{{ list|length }}<br>
</div>
页面展示
其他列表过滤器
- max - 获取列表中最大值
- min - 获取列表中最小值
自定义过滤器
定义一个反转列表的过滤器。
-
使用装饰器添加。 @app.template_filter('listreverse')
def list_reverse(li: list):
li.reverse()
return li
-
使用app实例添加。 def list_reverse(li: list):
li.reverse()
return li
app.add_template_filter(list_reverse, "listreverse")
展示效果
{{ list|listreverse }}
学习过程中遇到的报错
宏定义和使用的报错
jinja2.exceptions.TemplateSyntaxError: expected token ',', got 'username'
翻译:预期令牌’,‘,得到’username’。
原因:在引入宏定义的时候,没有添加上 name 参数名。
{% macro input(name, type='text', value='') -%}
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}">
{% endmacro %}
<div>
<p>用户名:{{ input('username') }}</p>
<p>密码:{{ input('password', type='password') }}</p>
</div>
解决方法:加上 name 参数名即解决。
<div>
<p>用户名:{{ input(name='username') }}</p>
<p>密码:{{ input(name='password', type='password') }}</p>
</div>
|