Jinja2 模版引擎
概要: jinja2 是一个快速高效的模版引擎
创建时间: 2023.11.05 21:56:06
更新时间: 2023.11.06 01:39:36
安装
jinja2 模板文件没有指定的后缀,可以使用 .jinja
或者任意的文本文件扩展名
{{ ... }}
变量
{{ x }}
如果是单个变量x
,可以使用 {{ x }}
语法获取 x
的值
{{ foo.bar }}
类似 Python 的 getattr
函数,可以用于获取对象或者字典的值
{{ foo['bar'] }}
类似 Python 的__getitem__
方法,也可以用于获取对象或者字典的值
区别
如果一个对象同时拥有上面两种方法,那么不同的调用方式会有优先级之分,如x['foo'] = bar1
且x.foo = bar2
,那么使用{{ foo.bar }}
时,渲染的结果是 bar2
,使用{{ foo['bar'] }}
时,渲染结果为 bar1
{% ... %}
逻辑
循环 for...endfor
提示
下面的变量后加上 |e
是为了安全转义,降低 HTML 漏洞攻击概率
列表循环
Bash |
---|
| <h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
|
字典循环
Bash |
---|
| <dl>
{% for key, value in my_dict.items() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
|
字典循环且排序
Bash |
---|
| <dl>
{% for key, value in my_dict | dictsort %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
|
特殊属性/方法
对一个可循环的变量,jinja2 内置了一些属性和方法供调用,详细用法可以参考官方文档 for

提前终止循环
在 jinja2 中无法实现,但是可以通过元素中的属性进行过滤,如
Bash |
---|
| {% for user in users if not user.hidden %}
<li>{{ user.username|e }}</li>
{% endfor %}
|
分支 if...endif
Bash |
---|
| {% if condition1 %}
This is condition 1.
{% elif condition2 %}
This is condition 2.
{% elif condition3 %}
This is condition 3.
{% else %}
This is the else block.
{% endif %}
|
转义 raw...endraw
简短文本可以通过单引号实现转义,如渲染两个尖括号可以使用 {{ '{{' }}
的写法。
如果是较为复杂的场景,需要使用 {% raw %}
实现,如
Bash |
---|
| {% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
|
宏 macros
TODO,参考 官方文档 Macros
继承 block...extends
单级继承 {{ super() }}
jinja2 通过在上级定义模版块 {{ block }}
,下级使用 {{ extends }}
关键词实现继承。
下面是上级被继承的模板文件 base.html
HTML |
---|
| <!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
{% endblock %}
</div>
</body>
</html>
|
下面是下级子文件 child.html
,继承自 base.html
,其中 {{ super }}
语法用于在上级模板的基础上,继续扩写此 block 的内容
HTML |
---|
| {% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome to my awesome homepage.
</p>
{% endblock %}
|
block 匹配
在上面的模板中,为了增强可读性,可以使用 {% block head %}
和 {% endblock head %}
这样的 block 对写法
多级继承 {{ super.super() }}
下面三级的文件内容如下,可以使用 {{ super.super() }}
实现只继承顶级模版内容
Bash |
---|
| # parent.jinja
body: {% block body %}Hi from parent.{% endblock %}
# child.jinja
{% extends "parent.jinja" %}
{% block body %}Hi from child. {{ super() }} {% endblock %}
# grandchild1.jinja
{% extends "child.jinja" %}
{% block body %}Hi from grandchild1.{% endblock %}
# grandchild2.jinja
{% extends "child.jinja" %}
{% block body %}Hi from grandchild2. {{ super() }} {% endblock %}
# grandchild3.jinja
{% extends "child.jinja" %}
{% block body %}Hi from grandchild3. {{ super.super() }} {% endblock %}
|
渲染结果为
Bash |
---|
| body: Hi from parent.
body: Hi from child. Hi from parent.
body: Hi from grandchild1.
body: Hi from grandchild2. Hi from child. Hi from parent.
body: Hi from grandchild3. Hi from parent.
|
block 作用域 scoped
在 block 渲染中,默认的变量作用域仅为当前级别模板,对子级别模板不可见,如在下面的模板中,如果子级别模板继承后,代码段 <li>
内是空的
Bash |
---|
| {% for item in seq %}
<li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}
|
此时,可以通过将 block 标记为 scoped
来显式标记 block 内的变量对子级别模板可见
Bash |
---|
| {% for item in seq %}
<li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
{% endfor %}
|
block 强制性 required
在下面的三级模板继承中, block body
被标记为必需的 block,否则渲染失败
Bash |
---|
| # page.txt
{% block body required %}{% endblock %}
# issue.txt
{% extends "page.txt" %}
# bug_report.txt
{% extends "issue.txt" %}
{% block body %}Provide steps to demonstrate the bug.{% endblock %}
|
其中,只有 bug_report.txt
可以被正常渲染,page.txt
和 issue.txt
会抛出异常 TemplateRuntimeError
scoped 与 required 优先级
required 必须在 scoped 之后出现
{% block body scoped %}{% endblock %}
{% block body required %}{% endblock %}
{% block body scoped required %}{% endblock %}
{# ... #}
注释
单行注释
Bash |
---|
| {# this is a jinja2 comment line, will not be rendered #}
|
多行注释
Bash |
---|
| {# note: commented-out template because we no longer use this
{% for user in users %}
...
{% endfor %}
#}
|
提示
注释虽然不会被渲染,但如果单行和多行注释会表现为一个空行
过滤器 Filter
jinja2 的 Filter 用于对变量的值进行过滤,常用于循环语句中
TODO
测试器 Tests
jinja2 的 Tests 用于对变量的值进行测试,常用于分支语句中
TODO
参考