模板设计器文档¶
本文档描述了模板引擎的语法和语义,对于创建Jinja模板的人来说,它将是最有用的参考。由于模板引擎非常灵活,应用程序的配置在分隔符和未定义值的行为方面可能与此处显示的代码略有不同。
简介¶
Jinja模板只是一个文本文件。Jinja可以生成任何基于文本的格式(HTML、XML、CSV、LaTex等)。Jinja模板不需要具有特定的扩展名: .html
, .xml
或者任何其他扩展都可以。
模板包含 变量 和/或 表达 ,当模板 提供 ;和 tags 控制模板的逻辑。模板语法深受Django和Python的启发。
下面是一个最小的模板,它演示了使用默认的jinja配置的一些基础知识。我们稍后将在本文档中介绍详细信息:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Webpage</title>
</head>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
<h1>My Webpage</h1>
{{ a_variable }}
{# a comment #}
</body>
</html>
以下示例显示默认配置设置。应用程序开发人员可以从 {{% foo %}}
到 <% foo %>
或者类似的东西。
有几种定界符。默认的jinja分隔符配置如下:
{% ... %}
for Statements{{{{ ... }}}}
对于 表达 打印到模板输出{{# ... #}}
对于 评论 不包括在模板输出中# ... ##
for Line Statements
模板文件扩展名¶
如上所述,任何文件都可以作为模板加载,而不考虑文件扩展名。添加 .jinja
延伸,比如 user.html.jinja
可能会使一些ide或编辑器插件更容易,但不是必需的。后面介绍的自动转义可以基于文件扩展名应用,因此在这种情况下,需要考虑额外的后缀。
另一个识别模板的好方法是它们在 templates
文件夹,不考虑扩展名。这是项目的常见布局。
变量¶
模板变量由传递给模板的上下文字典定义。
如果应用程序传入了模板中的变量,那么您可以随意处理这些变量。变量上可能有属性或元素,您也可以访问它们。变量的属性在很大程度上取决于提供该变量的应用程序。
你可以用圆点 (.
)访问除标准python之外的变量属性 __getitem__
“下标”语法 ([]
)
以下几行的作用相同:
{{ foo.bar }}
{{ foo['bar'] }}
重要的是要知道外部的双花括号是 not 变量的一部分,但打印语句。如果访问标记内的变量,不要在它们周围加括号。
如果变量或属性不存在,您将返回未定义的值。使用这种类型的值可以做什么取决于应用程序配置:默认行为是在打印或迭代时计算为空字符串,并在其他每个操作中失败。
实施
为了方便起见, foo.bar
在Jinja中,在Python层上执行以下操作:
检查调用的属性 bar 在 foo (
getattr(foo, 'bar')
)如果没有,检查项目
'bar'
在里面 foo (foo.__getitem__('bar')
)如果没有,则返回未定义的对象。
foo['bar']
工作原理基本相同,但顺序差异较小:
检查项目
'bar'
在里面 foo . (foo.__getitem__('bar')
)如果没有,请检查调用的属性 bar 在 foo . (
getattr(foo, 'bar')
)如果没有,则返回未定义的对象。
如果对象具有同名的项和属性,则这一点很重要。另外, attr()
筛选器仅查找属性。
过滤器¶
变量可以修改为 过滤器 . 过滤器通过管道符号与变量分离。 (|
)并且可以在括号中包含可选参数。可以链接多个过滤器。一个过滤器的输出应用于下一个过滤器。
例如, {{{{ name|striptags|title }}}}
将从变量中删除所有HTML标记 name 标题大小写输出 (title(striptags(name))
)
接受参数的过滤器在参数周围有圆括号,就像函数调用一样。例如: {{{{ listx|join(', ') }}}}
将以逗号加入列表 (str.join(', ', listx)
)
这个 内置过滤器列表 下面介绍所有内置过滤器。
测验¶
除了过滤器,还有所谓的“测试”可用。测试可用于根据公共表达式测试变量。要测试变量或表达式,请添加 is 加上变量后面的测试名称。例如,要确定是否定义了变量,可以执行以下操作 name is defined
,然后根据 name 在当前模板上下文中定义。
测试也可以接受参数。如果测试只接受一个参数,则可以省略括号。例如,以下两个表达式执行相同的操作:
{% if loop.index is divisibleby 3 %}
{% if loop.index is divisibleby(3) %}
这个 内置测试列表 下面介绍所有内置测试。
评论¶
要注释模板中的一行的一部分,请使用注释语法,默认设置为 {{# ... #}}
. 这对于注释模板的某些部分以进行调试或为其他模板设计器或您自己添加信息很有用:
{# note: commented-out template because we no longer use this
{% for user in users %}
...
{% endfor %}
#}
空白控件¶
在默认配置中:
如果存在单个尾随换行符,则去掉尾随换行符。
其他空白(空格、制表符、换行符等)返回时不变
如果应用程序将jinja配置为 trim_blocks ,自动删除模板标记后的第一个换行符(如在PHP中)。这个 lstrip_blocks 选项还可以设置为从一行的开头到块的开头剥离制表符和空格。(如果块开始之前还有其他字符,则不会删除任何内容。)
两者兼有 trim_blocks 和 lstrip_blocks 启用后,可以将块标记放在它们自己的行上,渲染时将删除整个块行,保留内容的空白。例如,如果没有 trim_blocks 和 lstrip_blocks 选项,此模板:
<div>
{% if True %}
yay
{% endif %}
</div>
在DIV:内用空行呈现:
<div>
yay
</div>
但两者兼而有之 trim_blocks 和 lstrip_blocks 启用后,将删除模板块行并保留其他空白:
<div>
yay
</div>
您可以手动禁用 lstrip_blocks 加加号的行为 (+
)在块的开头:
<div>
{%+ if something %}yay{% endif %}
</div>
类似地,您可以手动禁用 trim_blocks
加加号的行为 (+
)在一个街区的末尾:
<div>
{% if something +%}
yay
{% endif %}
</div>
您还可以手动去除模板中的空白。如果你加一个减号 (-
)到块的开始或结束(例如 为了 标记)、注释或变量表达式,将删除该块之前或之后的空白:
{% for item in seq -%}
{{ item }}
{%- endfor %}
这将生成所有元素,它们之间没有空白。如果 seq 是来自 1
到 9
,输出为 123456789
.
如果 行语句 如果启用,它们将自动删除行首空白,直到行首。
默认情况下,Jinja还会删除尾随的换行符。要保持单尾随换行符,请将Jinja配置为 keep_trailing_newline .
注意
不能在标记和减号之间添加空白。
有效的 ::
{%- if foo -%}...{% endif %}
无效 ::
{% - if foo - %}...{% endif %}
逃逸¶
有时,甚至有必要让Jinja忽略它将作为变量或块处理的部分。例如,如果要使用默认语法 {{{{
作为模板中的原始字符串而不是变量的开头,必须使用技巧。
输出文本变量分隔符的最简单方法 ({{{{
)是通过使用变量表达式::
{{ '{{' }}
对于较大的部分,标记块是有意义的 raw . 例如,要在模板中包含示例jinja语法,可以使用以下代码段:
{% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
注意
结尾的减号 {{% raw -%}}
标记将清除原始数据第一个字符前面的所有空格和换行符。
行语句¶
如果应用程序启用了行语句,则可以将行标记为语句。例如,如果行语句前缀配置为 #
,以下两个示例是等效的:
<ul>
# for item in seq
<li>{{ item }}</li>
# endfor
</ul>
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
行语句前缀可以出现在行的任何位置,只要行前面没有文本。为了提高可读性,启动块的语句(例如 for , if , elif 等)可能以冒号结尾:
# for item in seq:
...
# endfor
注意
如果有左括号、大括号或括号,则line语句可以跨多行:
<ul>
# for href, caption in [('index.html', 'Index'),
('about.html', 'About')]:
<li><a href="{{ href }}">{{ caption }}</a></li>
# endfor
</ul>
自Jinja 2.2以来,基于行的评论也可用。例如,如果行注释前缀配置为 ##
,来自的所有内容 ##
忽略行尾(不包括换行符)::
# for item in seq:
<li>{{ item }}</li> ## this comment is ignored
# endfor
模板继承¶
Jinja最强大的部分是模板继承。模板继承允许您构建一个基本的“骨架”模板,该模板包含站点的所有公共元素并定义 阻碍 子模板可以重写。
听起来很复杂,但很基本。从一个例子开始,很容易理解它。
基本模板¶
我们将调用此模板 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 %}
© Copyright 2008 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
</html>
在这个例子中, {{% block %}}
标记定义了子模板可以填充的四个块。所有的 block 标记的作用是告诉模板引擎子模板可能会覆盖模板中的那些占位符。
block
标记可以位于其他块中,例如 if
,但无论 if
块实际上已渲染。
子模板¶
子模板可能如下所示:
{% 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 %}
这个 {{% extends %}}
标签是这里的关键。它告诉模板引擎这个模板“扩展”了另一个模板。当模板系统评估此模板时,它首先定位父模板。扩展标记应该是模板中的第一个标记。在它正常打印之前的所有内容都可能导致混乱。有关此行为以及如何利用它的详细信息,请参阅 空主回退 . 此外,无论周围条件的计算结果是真还是假,都将始终填充一个块。
模板的文件名取决于模板加载器。例如, FileSystemLoader
允许您通过提供文件名来访问其他模板。可以使用斜线访问子目录中的模板::
{% extends "layout/default.html" %}
但是这种行为可以依赖于嵌入jinja的应用程序。注意,由于子模板没有定义 footer
块,使用父模板中的值。
不能定义多个 {{% block %}}
起源 . 如果有两个相似的名字 {{% block %}}
标记在模板中,该模板的父级将不知道要使用哪个块的内容。
如果要多次打印一个块,则可以使用 self 变量并使用该名称调用块:
<title>{% block title %}{% endblock %}</title>
<h1>{{ self.title() }}</h1>
{% block body %}{% endblock %}
超级街区¶
可以通过调用 super()
. 这将返回父块的结果:
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ super() }}
{% endblock %}
嵌套延伸¶
在多个级别的情况下 {{% extends %}}
, super
引用可以被链接(如 super.super()
)跳过继承树中的级别。
例如::
# parent.tmpl
body: {% block body %}Hi from parent.{% endblock %}
# child.tmpl
{% extends "parent.tmpl" %}
{% block body %}Hi from child. {{ super() }}{% endblock %}
# grandchild1.tmpl
{% extends "child.tmpl" %}
{% block body %}Hi from grandchild1.{% endblock %}
# grandchild2.tmpl
{% extends "child.tmpl" %}
{% block body %}Hi from grandchild2. {{ super.super() }} {% endblock %}
致使 child.tmpl
将给予 body: Hi from child. Hi from parent.
致使 grandchild1.tmpl
将给予 body: Hi from grandchild1.
致使 grandchild2.tmpl
将给予 body: Hi from grandchild2. Hi from parent.
命名块结束标记¶
Jinja允许您将块的名称放在结束标记之后,以提高可读性:
{% block sidebar %}
{% block inner_sidebar %}
...
{% endblock inner_sidebar %}
{% endblock sidebar %}
但是,名称后面的 endblock Word必须与块名称匹配。
块嵌套和范围¶
块可以嵌套用于更复杂的布局。但是,每个默认块可能无法从外部作用域访问变量:
{% for item in seq %}
<li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}
此示例将输出为空 <li>
项目因为 item 在块内不可用。这样做的原因是,如果块被子模板替换,则会出现一个未在块中定义或传递给上下文的变量。
从jinja 2.2开始,通过添加 scoped 块声明的修饰符::
{% for item in seq %}
<li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
{% endfor %}
当覆盖块时, scoped 不必提供修饰符。
所需的数据块¶
可以根据需要标记块。它们必须在某个时候被覆盖,但不一定要被直接子模板覆盖。必需的块只能包含空格或注释,并且不能直接呈现。
例如::
# parent.tmpl
body: {% block body required %}{% endblock %}
# child.tmpl
{% extends "parent.tmpl" %}
# grandchild.tmpl
{% extends "child.tmpl" %}
{% block body %}Hi from grandchild.{% endblock %}
渲染 child.tmpl
会给你 TemplateRuntimeError
渲染 grandchild.tmpl
会给你 Hi from grandchild.
当与 scoped
,即 required
必须放置修饰符 after 限定范围的修饰符。以下是一些有效的示例:
{% block body scoped %}{% endblock %}
{% block body required %}{% endblock %}
{% block body scoped required %}{% endblock %}
模板对象¶
Changelog
在 2.4 版本发生变更.
如果模板对象是在模板上下文中传递的,则也可以从该对象进行扩展。假设调用代码将布局模板作为 layout_template 对于环境,此代码的作用是:
{% extends layout_template %}
以前, layout_template 变量必须是具有布局模板文件名的字符串才能工作。
HTML逃逸¶
当从模板生成HTML时,变量总是存在包含影响结果HTML的字符的风险。有两种方法:
手动转义每个变量;或
默认情况下自动转义所有内容。
Jinja支持两者。使用什么取决于应用程序配置。默认配置不是自动转义;由于各种原因:
转义除安全值之外的所有内容还意味着Jinja转义的变量不包括HTML(例如数字、布尔值),这可能会对性能造成巨大影响。
有关变量安全性的信息非常脆弱。通过强制安全和不安全的值,返回值可能是双转义的HTML。
使用手动逃逸¶
如果启用了手动转义,则 your 如有必要,负责逃逸变量。怎么逃跑?如果你有一个变量 may 包括以下任何字符 (>
, <
, &
或 "
你 SHOULD 除非变量包含格式良好且受信任的HTML,否则对其进行转义。通过管道将变量通过 |e
过滤器:
{{ user.username|e }}
使用自动转义¶
启用自动转义后,默认情况下,除了显式标记为安全的值外,所有内容都转义。变量和表达式可以在以下位置标记为安全:
应用程序的上下文字典
markupsafe.Markup
模板,带有
|safe
过滤器。
如果您标记为安全的字符串通过其他不理解该标记的Python代码传递,它可能会丢失。在到达模板之前,请注意何时将数据标记为安全的,以及如何处理这些数据。
如果某个值已转义但未标记为安全,则仍将自动转义并导致双转义字符。如果您知道您的数据已经是安全的但没有标记,请确保将其包装起来 Markup
或者使用 |safe
过滤器。
Jinja函数(宏, super , self.BLOCKNAME )始终返回标记为安全的模板数据。
带有自动转义的模板中的字符串文字被认为是不安全的,因为本机Python字符串不安全。
控制结构清单¶
控制结构指的是控制程序流的所有东西——循环的条件(即if/elif/else),以及宏和块之类的东西。使用默认语法,控件结构出现在 {{% ... %}}
阻碍。
为了¶
按顺序循环每个项。例如,显示在变量中提供的用户列表 users ::
<h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
由于模板中的变量保留其对象属性,因此可以在类似 dict ::
<dl>
{% for key, value in my_dict.items() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
但是,请注意 未订购python dict ;因此,您可能希望通过 list
属于 tuple
S-或A collections.OrderedDict
--到模板,或使用 dictsort 过滤器。
在for循环块内,可以访问一些特殊变量:
变量 |
描述 |
---|---|
loop.index |
循环的当前迭代。(1索引) |
loop.index0 |
循环的当前迭代。(0索引) |
loop.revindex |
循环结束时的迭代次数(1个索引) |
loop.revindex0 |
循环结束时的迭代次数(0个索引) |
loop.first |
如果第一次迭代为真。 |
loop.last |
如果上次迭代为真。 |
loop.length |
序列中的项数。 |
loop.cycle |
在序列列表之间循环的辅助函数。请参阅下面的解释。 |
loop.depth |
指示当前呈现在递归循环中的深度。从1级开始 |
loop.depth0 |
指示当前呈现在递归循环中的深度。从0级开始 |
loop.previtem |
循环上一次迭代中的项。在第一次迭代期间未定义。 |
loop.nextitem |
循环的以下迭代中的项。上次迭代时未定义。 |
loop.changed(*val) |
如果以前使用其他值调用(或根本不调用),则为true。 |
在for循环中,可以通过使用 loop.cycle 帮手::
{% for row in rows %}
<li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}
自Jinja2.1以来,额外 cycle 存在允许循环未绑定循环的帮助程序。有关更多信息,请查看 全局函数列表 .
与Python不同,它不可能 break 或 continue 在一个循环中但是,您可以在迭代期间过滤序列,这允许您跳过项目。以下示例跳过所有隐藏的用户:
{% for user in users if not user.hidden %}
<li>{{ user.username|e }}</li>
{% endfor %}
优势在于 loop 变量将正确计数;因此不计算未迭代的用户。
如果由于序列为空或筛选删除了序列中的所有项而没有进行迭代,则可以使用 else ::
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% else %}
<li><em>no users found</em></li>
{% endfor %}
</ul>
注意,在python中, else 每当相应的循环 没有 break . 因为Jinja环路不能 break 总之,一个稍微不同的行为 else 已选择关键字。
也可以递归地使用循环。如果您正在处理递归数据(如站点地图或RDFA),这将非常有用。要递归地使用循环,基本上必须添加 recursive 循环定义的修饰符并调用 loop 变量,新的iterable位于要递归的位置。
以下示例使用递归循环实现站点地图:
<ul class="sitemap">
{%- for item in sitemap recursive %}
<li><a href="{{ item.href|e }}">{{ item.title }}</a>
{%- if item.children -%}
<ul class="submenu">{{ loop(item.children) }}</ul>
{%- endif %}</li>
{%- endfor %}
</ul>
这个 loop 变量总是指最近的(最里面的)循环。如果我们有多个级别的循环,我们可以重新绑定变量 loop 通过写入 {{% set outer_loop = loop %}} 在循环之后,我们要递归使用。然后,我们可以用 {{{{ outer_loop(...) }}}}
请注意,循环中的赋值将在迭代结束时清除,并且不能超过循环范围。旧版本的Jinja有一个bug,在某些情况下,任务似乎可以工作。不支持此操作。看到了吗 作业 有关如何处理此问题的详细信息。
如果您只想检查某个值自上次迭代以来是否发生了更改,或者在下一次迭代中将发生更改,则可以使用 previtem 和 nextitem ::
{% for value in values %}
{% if loop.previtem is defined and value > loop.previtem %}
The value just increased!
{% endif %}
{{ value }}
{% if loop.nextitem is defined and loop.nextitem > value %}
The value will increase even more!
{% endif %}
{% endfor %}
如果您只关心值是否发生了变化,请使用 changed 更容易:
{% for entry in entries %}
{% if loop.changed(entry.category) %}
<h2>{{ entry.category }}</h2>
{% endif %}
<p>{{ entry.message }}</p>
{% endfor %}
如果¶
这个 if jinja中的语句与python if语句相当。在最简单的形式中,您可以使用它来测试是否定义了变量,不是空的,也不是假的:
{% if users %}
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}
对于多个分支, elif 和 else 可以像在Python中那样使用。你可以使用更复杂的 表达 也有:
{% if kenny.sick %}
Kenny is sick.
{% elif kenny.dead %}
You killed Kenny! You bastard!!!
{% else %}
Kenny looks okay --- so far
{% endif %}
如果还可以用作 inline expression 为了 loop filtering .
宏指令¶
宏可以与常规编程语言中的函数进行比较。将经常使用的习惯用法放入可重用的函数中以避免重复(“dry”)。
下面是呈现表单元素的宏的一个小示例:
{% macro input(name, value='', type='text', size=20) -%}
<input type="{{ type }}" name="{{ name }}" value="{{
value|e }}" size="{{ size }}">
{%- endmacro %}
然后可以像命名空间中的函数那样调用宏::
<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>
如果宏是在其他模板中定义的,则必须 import 首先。
在宏内部,您可以访问三个特殊变量:
- varargs
如果传递给宏的位置参数多于宏接受的位置参数,则它们最终会出现在 varargs 变量作为值列表。
- kwargs
喜欢 varargs 但对于关键字参数。所有未使用的关键字参数都存储在这个特殊变量中。
- caller
如果宏是从 call 标记,调用方作为可调用宏存储在此变量中。
宏还公开了一些内部细节。以下属性在宏对象上可用:
- name
宏的名称。
{{{{ input.name }}}}
将打印input
.- arguments
宏接受的参数名称的元组。
- defaults
默认值的元组。
- catch_kwargs
这是 true 如果宏接受额外的关键字参数(即:访问 kwargs 变量)。
- catch_varargs
这是 true 如果宏接受额外的位置参数(即:访问 varargs 变量)。
- caller
这是 true 如果宏访问 caller 变量,可以从 call 标签。
如果宏名以下划线开头,则不会导出宏名,也无法导入宏名。
呼叫¶
在某些情况下,将宏传递给另一个宏可能很有用。为此,您可以使用 call 块。下面的示例显示了一个宏,它利用了调用功能以及如何使用它:
{% macro render_dialog(title, class='dialog') -%}
<div class="{{ class }}">
<h2>{{ title }}</h2>
<div class="contents">
{{ caller() }}
</div>
</div>
{%- endmacro %}
{% call render_dialog('Hello World') %}
This is a simple dialog rendered by using a macro and
a call block.
{% endcall %}
也可以将参数传递回调用块。这使得它可以用作循环的替换。一般来说,调用块的工作方式与没有名称的宏完全相同。
以下是如何将调用块与参数一起使用的示例:
{% macro dump_users(users) -%}
<ul>
{%- for user in users %}
<li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
{%- endfor %}
</ul>
{%- endmacro %}
{% call(user) dump_users(list_of_user) %}
<dl>
<dt>Realname</dt>
<dd>{{ user.realname|e }}</dd>
<dt>Description</dt>
<dd>{{ user.description }}</dd>
</dl>
{% endcall %}
过滤器¶
过滤器部分允许您对模板数据块应用常规的Jinja过滤器。把代码包装在特殊的 filter 章节:
{% filter upper %}
This text becomes uppercase
{% endfilter %}
作业¶
在代码块内,还可以为变量赋值。顶层(块、宏或循环之外)的工作分配与顶层宏一样从模板中导出,并且可以由其他模板导入。
工作分配使用 set 标记并可以有多个目标:
{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
{% set key, value = call_something() %}
范围界定行为
请记住,不可能在一个块内设置变量并让它们显示在块外。这也适用于循环。唯一的例外是不引入范围的if语句。因此,以下模板不会执行您可能期望的操作:
{% set iterated = false %}
{% for item in seq %}
{{ item }}
{% set iterated = true %}
{% endfor %}
{% if not iterated %} did not iterate {% endif %}
使用jinja语法是不可能做到这一点的。相反,使用循环else块或特殊的 loop 变量::
{% for item in seq %}
{{ item }}
{% else %}
did not iterate
{% endfor %}
从2.10版开始,可以使用允许跨作用域传播更改的命名空间对象来处理更复杂的用例:
{% set ns = namespace(found=false) %}
{% for item in items %}
{% if item.check_something() %}
{% set ns.found = true %}
{% endif %}
* {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}
请注意 obj.attr
符号表示法 set 标记只允许用于命名空间对象;尝试在任何其他对象上分配属性将引发异常。
Changelog
在 2.10 版本加入: 添加了对命名空间对象的支持
阻止分配¶
Changelog
在 2.8 版本加入.
从Jinja2.8开始,还可以使用块分配将块的内容捕获到变量名中。在某些情况下,这可以作为宏的替代方法。在这种情况下,不使用等号和值,只需编写变量名,然后编写所有内容,直到 {{% endset %}}
被捕获。
例子::
{% set navigation %}
<li><a href="/">Index</a>
<li><a href="/downloads">Downloads</a>
{% endset %}
这个 navigation 然后变量包含导航HTML源代码。
Changelog
在 2.10 版本发生变更.
从Jinja 2.10开始,块分配支持过滤器。
例子::
{% set reply | wordwrap %}
You wrote:
{{ message }}
{% endset %}
包括¶
这个 include 标记用于包含模板并将该文件的呈现内容返回到当前命名空间::
{% include 'header.html' %}
Body
{% include 'footer.html' %}
默认情况下,包含的模板可以访问活动上下文的变量。有关导入和包含的上下文行为的详细信息,请参阅 导入上下文行为 .
从Jinja 2.2起,您可以标记包含 ignore missing
;在这种情况下,如果要包含的模板不存在,Jinja将忽略该语句。当与 with
或 without context
,必须放置 之前 上下文可见性语句。以下是一些有效的示例:
{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
Changelog
在 2.2 版本加入.
还可以提供在包含之前已检查是否存在的模板列表。将包括存在的第一个模板。如果 ignore missing 如果不存在任何模板,则返回到“不渲染”,否则将引发异常。
例子::
{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
Changelog
在 2.4 版本发生变更: 如果模板对象已传递到模板上下文,则可以使用 include .
输入¶
Jinja支持将常用代码放入宏中。这些宏可以进入不同的模板并从中导入。这类似于Python中的import语句。重要的是要知道导入是缓存的,导入的模板不能访问当前的模板变量,默认情况下只有全局变量。有关导入和包含的上下文行为的更多详细信息,请参阅 导入上下文行为 .
导入模板有两种方法。您可以将完整的模板导入到变量中,或者从变量中请求特定的宏/导出变量。
假设我们有一个呈现表单的助手模块(称为 forms.html ):
{% macro input(name, value='', type='text') -%}
<input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
{%- endmacro %}
{%- macro textarea(name, value='', rows=10, cols=40) -%}
<textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols
}}">{{ value|e }}</textarea>
{%- endmacro %}
访问模板变量和宏的最简单和最灵活的方法是将整个模板模块导入到变量中。这样,您就可以访问以下属性:
{% import 'forms.html' as forms %}
<dl>
<dt>Username</dt>
<dd>{{ forms.input('username') }}</dd>
<dt>Password</dt>
<dd>{{ forms.input('password', type='password') }}</dd>
</dl>
<p>{{ forms.textarea('comment') }}</p>
或者,可以将特定名称从模板导入当前命名空间::
{% from 'forms.html' import input as input_field, textarea %}
<dl>
<dt>Username</dt>
<dd>{{ input_field('username') }}</dd>
<dt>Password</dt>
<dd>{{ input_field('password', type='password') }}</dd>
</dl>
<p>{{ textarea('comment') }}</p>
以一个或多个下划线开头的宏和变量是私有的,无法导入。
Changelog
在 2.4 版本发生变更: 如果模板对象已传递到模板上下文,则可以从该对象导入。
导入上下文行为¶
默认情况下,所包含的模板将传递到当前上下文,而导入的模板则不传递。这样做的原因是,与include不同,导入被缓存;因为导入通常被用作保存宏的模块。
此行为可以显式更改:通过添加 with context 或 without context 对于import/include指令,可以将当前上下文传递到模板,并自动禁用缓存。
以下是两个例子:
{% from 'forms.html' import input with context %}
{% include 'header.html' without context %}
注意
在Jinja2.0中,传递给包含模板的上下文不包括模板中定义的变量。事实上,这不起作用:
{% for box in boxes %}
{% include "render_box.html" %}
{% endfor %}
包含的模板 render_box.html
是 not 能够访问 box 在Jinja2。从Jinja 2.1开始, render_box.html
is 能够做到这一点。
表达¶
Jinja允许在任何地方使用基本的表达方式。这些方法与普通的python非常相似;即使您不使用python,也应该对它感到舒适。
直接常量¶
最简单的表达式形式是文本。文本是Python对象(如字符串和数字)的表示形式。存在以下文字:
"Hello World"
两个双引号或单引号之间的所有内容都是字符串。当您需要模板中的字符串时(例如,作为函数调用和筛选器的参数,或者只是为了扩展或包含模板),它们都非常有用。
42
/123_456
整数是不带小数部分的整数。“字符”可用于分隔组以确保易读性。
42.23
/42.1e2
/123_456.789
浮点数可以用“.”作为小数点。它们也可以用科学记数法写成,用大写或小写字母“e”表示指数部分。“字符”可用于分隔组以确保易读性,但不能用于指数部分。
['list', 'of', 'objects']
两个括号之间的所有内容都是一个列表。列表对于存储要迭代的顺序数据很有用。例如,可以使用for(和with)for循环的列表和元组轻松创建链接列表:
<ul> {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'), ('downloads.html', 'Downloads')] %} <li><a href="{{ href }}">{{ caption }}</a></li> {% endfor %} </ul>
('tuple', 'of', 'values')
元组类似于无法修改的列表(“不可变”)。如果一个元组只有一个项,它必须后跟一个逗号。 (
('1-tuple',)
)元组通常用于表示两个或多个元素的项。有关详细信息,请参阅上面的列表示例。{'dict': 'of', 'key': 'and', 'value': 'pairs'}
python中的dict是一种组合键和值的结构。键必须唯一,并且始终只有一个值。口述在模板中很少使用;它们在一些罕见的情况下很有用,例如
xmlattr()
过滤器。true
/false
true
总是正确的而且false
总是假的。
注意
特殊常数 true , false 和 none 确实是小写的。因为这在过去引起了混乱, (True 用于扩展到被认为是错误的未定义变量),现在这三个变量都可以用标题大小写 (True , False 和 None )但是,为了一致性,(所有的Jinja标识符都是小写的),您应该使用小写版本。
数学¶
Jinja允许您使用值进行计算。这在模板中很少有用,但为了完整性而存在。支持以下运算符:
+
将两个对象添加到一起。通常,对象都是数字,但如果两者都是字符串或列表,则可以这样连接它们。但是,这不是连接字符串的首选方法!对于字符串连接,请查看
~
运算符。{{{{ 1 + 1 }}}}
是2
.-
从第一个数中减去第二个数。
{{{{ 3 - 2 }}}}
是1
./
把两个数字分开。返回值将是一个浮点数。
{{{{ 1 / 2 }}}}
是{{{{ 0.5 }}}}
.//
将两个数字相除并返回截断的整数结果。
{{{{ 20 // 7 }}}}
是2
.%
计算整数除法的余数。
{{{{ 11 % 7 }}}}
是4
.*
将左操作数与右操作数相乘。
{{{{ 2 * 2 }}}}
会回来4
. 这也可以用于多次重复字符串。{{{{ '=' * 80 }}}}
将打印一个80等号的条。**
将左操作数提高到右操作数的幂。
{{{{ 2**3 }}}}
会回来8
.
比较¶
==
比较两个对象是否相等。
!=
比较两个对象的不等式。
>
true
如果左侧大于右侧。>=
true
如果左侧大于或等于右侧。<
true
如果左侧低于右侧。<=
true
如果左侧低于或等于右侧。
逻辑¶
为了 if
声明, for
过滤,以及 if
表达式,组合多个表达式可能很有用:
and
如果左操作数和右操作数为真,则返回真。
or
如果左操作数或右操作数为真,则返回真。
not
否定一个陈述(见下文)。
(expr)
括号将表达式分组。
注意
这个 is
和 in
运算符也支持使用中缀表示法求反: foo is not bar
和 foo not in bar
而不是 not foo is bar
和 not foo in bar
. 所有其他表达式都需要前缀表示法: not (foo and bar).
其他经营者¶
以下运算符非常有用,但不适用于其他两个类别:
in
执行序列/映射控制测试。如果左操作数包含在右操作数中,则返回true。
{{{{ 1 in [1, 2, 3] }}}}
例如,将返回true。is
执行一个 test .
|
应用A filter .
~
将所有操作数转换为字符串并将它们连接起来。
{{{{ "Hello " ~ name ~ "!" }}}}
将返回(假设 name 设置为'John'
)Hello John!
.()
呼叫可呼叫:
{{{{ post.render() }}}}
. 在圆括号内,可以使用位置参数和关键字参数,如在python中:{{{{ post.render(user, full=true) }}}}
..
/[]
获取对象的属性。(见 变量 )
if表达式¶
也可以使用内联 if 表达。这些在某些情况下是有用的。例如,如果定义了变量,则可以使用此从一个模板扩展,否则从默认布局模板扩展:
{% extends layout_template if layout_template is defined else 'master.html' %}
一般的语法是 <do something> if <something is true> else <do something else>
.
这个 else 零件是可选的。如果未提供,else块隐式计算为 Undefined
对象(不管什么 undefined
环境中设置为:
{{ "[{}]".format(page.title) if page.title }}
Python方法¶
您还可以使用在变量类型上定义的任何方法。从方法调用返回的值用作表达式的值。下面是一个使用在字符串上定义的方法的示例(其中 page.title
是一个字符串):
{{ page.title.capitalize() }}
这适用于用户定义类型上的方法。例如,if变量 f
类型的 Foo
有方法吗 bar
在其上定义,可以执行以下操作:
{{ f.bar(value) }}
运算符方法也按预期工作。例如, %
为字符串实现printf样式:
{{ "Hello, %s!" % name }}
虽然你应该更喜欢 .format
方法(在呈现模板的上下文中有点做作):
{{ "Hello, {}!".format(name) }}
内置过滤器列表¶
- abs(x, /)¶
返回参数的绝对值。
- attr(obj: Any, name: str) Union[jinja2.runtime.Undefined, Any] ¶
获取对象的属性。
foo|attr("bar")
工作原理类似foo.bar
只是始终返回一个属性,而不查找项。见 Notes on subscriptions 了解更多详细信息。
- batch(value: 't.Iterable[V]', linecount: int, fill_with: 't.Optional[V]' = None) 't.Iterator[t.List[V]]' ¶
批处理项目的筛选器。它的工作原理很像 slice 正好相反。它返回具有给定项数的列表列表。如果提供第二个参数,则用于填充缺少的项。请参见以下示例:
<table> {%- for row in items|batch(3, ' ') %} <tr> {%- for column in row %} <td>{{ column }}</td> {%- endfor %} </tr> {%- endfor %} </table>
- default(value: V, default_value: V = '', boolean: bool = False) V ¶
如果该值未定义,则返回传递的默认值,否则返回变量的值:
{{ my_variable|default('my_variable is not defined') }}
这将输出
my_variable
如果变量已定义,否则'my_variable is not defined'
. 如果要对值为false的变量使用默认值,则必须将第二个参数设置为 true :{{ ''|default('the string was empty', true) }}
Changelog
在 2.11 版本发生变更: 现在可以配置
Environment
具有ChainableUndefined
使 default 过滤器处理嵌套元素和属性,这些元素和属性在链中可能包含未定义的值,而不会获得UndefinedError
.- 别名
d
- dictsort(value: Mapping[K, V], case_sensitive: bool = False, by: 'te.Literal["key", "value"]' = 'key', reverse: bool = False) List[Tuple[K, V]] ¶
对字典进行排序并生成(键、值)对。Python词典的显示顺序可能与您希望的不同,因此请先对它们进行排序。
{% for key, value in mydict|dictsort %} sort the dict by key, case insensitive {% for key, value in mydict|dictsort(reverse=true) %} sort the dict by key, case insensitive, reverse order {% for key, value in mydict|dictsort(true) %} sort the dict by key, case sensitive {% for key, value in mydict|dictsort(false, 'value') %} sort the dict by value, case insensitive
- escape(value)¶
替换字符
&
,<
,>
,'
,以及"
在具有HTML安全序列的字符串中。如果需要在HTML中显示可能包含此类字符的文本,请使用此选项。如果该对象具有
__html__
方法,则会调用该方法,并且假定返回值对于HTML已经是安全的。- 参数
s -- 要转换为字符串并转义的对象。
- 返回
A
Markup
包含转义文本的字符串。- 别名
e
- filesizeformat(value: Union[str, float, int], binary: bool = False) str ¶
将值格式化为“人类可读”的文件大小(即13 KB、4.1 MB、102字节等)。如果第二个参数设置为,则使用默认的十进制前缀(mega、giga等)。 True 使用二进制前缀(mebi、gibi)。
- first(seq: 't.Iterable[V]') 't.Union[V, Undefined]' ¶
返回序列的第一项。
- forceescape(value: 't.Union[str, HasHTML]') markupsafe.Markup ¶
强制HTML转义。这可能会使转义变量加倍。
- format(value: str, *args: Any, **kwargs: Any) str ¶
将给定值应用于 printf-style 格式化字符串,例如
string % values
.{{ "%s, %s!"|format(greeting, name) }} Hello, World!
在大多数情况下,使用
%
操作员或str.format()
.{{ "%s, %s!" % (greeting, name) }} {{ "{}, {}!".format(greeting, name) }}
- groupby(value: 't.Iterable[V]', attribute: Union[str, int], default: Optional[Any] = None, case_sensitive: bool = False) 't.List[_GroupTuple]' ¶
使用Python的
itertools.groupby()
. 属性可以对嵌套访问使用点表示法,例如"address.city"
. 不像Python的groupby
,首先对值进行排序,因此每个唯一值只返回一个组。例如,列表
User
对象与Acity
属性可以分组呈现。在这个例子中,grouper
指的是city
组的值。<ul>{% for city, items in users|groupby("city") %} <li>{{ city }} <ul>{% for user in items %} <li>{{ user.name }} {% endfor %}</ul> </li> {% endfor %}</ul>
groupby
产生的命名成对(grouper, list)
,它可以代替上面的元组解包。grouper
属性的值,并且list
是具有该值的项。<ul>{% for group in users|groupby("city") %} <li>{{ group.grouper }}: {{ group.list|join(", ") }} {% endfor %}</ul>
您可以指定
default
当列表中的对象没有给定属性时使用的值。<ul>{% for city, items in users|groupby("city", default="NY") %} <li>{{ city }}: {{ items|map(attribute="name")|join(", ") }}</li> {% endfor %}</ul>
就像
sort()
默认情况下,筛选、排序和分组不区分大小写。这个key
对于每个组,将具有该组值中第一项的大小写。例如,如果用户列表包含城市["CA", "NY", "ca"]
,“CA”组将有两个值。这可以通过传递以下命令来禁用case_sensitive=True
。在 3.1 版本发生变更: 添加了
case_sensitive
参数。默认情况下,排序和分组不区分大小写,与执行比较的其他筛选器匹配。Changelog
在 3.0 版本发生变更: 增加了
default
参数。在 2.6 版本发生变更: 该属性支持嵌套访问的点表示法。
- indent(s: str, width: Union[int, str] = 4, first: bool = False, blank: bool = False) str ¶
返回字符串的副本,每行缩进4个空格。默认情况下,首行和空行不缩进。
- 参数
width -- 要缩进的空格或字符串的数量。
first -- 不要跳过首行缩进。
blank -- 不要跳过空行缩进。
Changelog
在 3.0 版本发生变更:
width
可以是字符串。在 2.10 版本发生变更: 默认情况下,空行不缩进。
重命名
indentfirst
参数first
.
- int(value: Any, default: int = 0, base: int = 10) int ¶
将该值转换为整数。如果转换不起作用,它将返回
0
. 可以使用第一个参数覆盖此默认值。您还可以重写第二个参数中的默认基数(10),该参数用前缀(如0b、0o和0x)分别处理基数2、8和16的输入。十进制数和非字符串值的基数被忽略。
- items(value: Union[Mapping[K, V], jinja2.runtime.Undefined]) Iterator[Tuple[K, V]] ¶
返回一个迭代器
(key, value)
映射的项。x|items
与之相同x.items()
,除非符合以下条件x
如果未定义,则返回空迭代器。如果希望使用另一种编程语言的JJJA实现呈现模板,则此筛选器非常有用
.items()
方法的映射类型。<dl> {% for key, value in my_dict|items %} <dt>{{ key }} <dd>{{ value }} {% endfor %} </dl>
在 3.1 版本加入.
- join(value: Iterable, d: str = '', attribute: Union[str, int, NoneType] = None) str ¶
返回一个字符串,该字符串是序列中字符串的串联。元素之间的分隔符默认为空字符串,您可以使用可选参数定义它:
{{ [1, 2, 3]|join('|') }} -> 1|2|3 {{ [1, 2, 3]|join }} -> 123
也可以连接对象的某些属性:
{{ users|join(', ', attribute='username') }}
Changelog
在 2.6 版本加入: 这个 attribute 已添加参数。
- last(seq: 't.Reversible[V]') 't.Union[V, Undefined]' ¶
返回序列的最后一项。
注意:不适用于发电机。您可能需要显式地将其转换为列表:
{{ data | selectattr('name', '==', 'Jinja') | list | last }}
- length(obj, /)¶
返回容器中的项目数。
- 别名
count
- list(value: 't.Iterable[V]') 't.List[V]' ¶
将值转换为列表。如果是字符串,则返回的列表将是字符列表。
- map(value: Iterable, *args: Any, **kwargs: Any) Iterable ¶
对对象序列应用筛选器或查找属性。这在处理对象列表时很有用,但实际上您只对对象的某个值感兴趣。
基本用法是对属性进行映射。假设您有一个用户列表,但您只对一个用户名列表感兴趣:
Users on this page: {{ users|map(attribute='username')|join(', ') }}
您可以指定
default
当列表中的对象没有给定属性时使用的值。{{ users|map(attribute="username", default="Anonymous")|join(", ") }}
或者,您可以让它通过在后面传递过滤器的名称和参数来调用过滤器。一个很好的例子是对序列应用文本转换过滤器:
Users on this page: {{ titles|map('lower')|join(', ') }}
与生成器理解类似,例如:
(u.username for u in users) (getattr(u, "username", "Anonymous") for u in users) (do_lower(x) for x in titles)
Changelog
在 2.11.0 版本发生变更: 增加了
default
参数。在 2.7 版本加入.
- max(value: 't.Iterable[V]', case_sensitive: bool = False, attribute: Union[str, int, NoneType] = None) 't.Union[V, Undefined]' ¶
返回序列中最大的项。
{{ [1, 2, 3]|max }} -> 3
- 参数
case_sensitive -- 将大小写字符串视为不同的字符串。
attribute -- 获取具有此属性最大值的对象。
- min(value: 't.Iterable[V]', case_sensitive: bool = False, attribute: Union[str, int, NoneType] = None) 't.Union[V, Undefined]' ¶
返回序列中最小的项。
{{ [1, 2, 3]|min }} -> 1
- 参数
case_sensitive -- 将大小写字符串视为不同的字符串。
attribute -- 获取具有此属性最小值的对象。
- random(seq: 't.Sequence[V]') 't.Union[V, Undefined]' ¶
从序列中返回随机项。
- reject(value: 't.Iterable[V]', *args: Any, **kwargs: Any) 't.Iterator[V]' ¶
通过对每个对象应用一个测试来筛选一系列对象,并在测试成功后拒绝这些对象。
如果未指定测试,则每个对象都将作为布尔值进行计算。
示例用法:
{{ numbers|reject("odd") }}
与生成器理解类似,例如:
(n for n in numbers if not test_odd(n))
Changelog
在 2.7 版本加入.
- rejectattr(value: 't.Iterable[V]', *args: Any, **kwargs: Any) 't.Iterator[V]' ¶
通过对每个对象的指定属性应用测试,并在测试成功后拒绝对象,来筛选对象序列。
如果未指定测试,则属性的值将作为布尔值进行计算。
{{ users|rejectattr("is_active") }} {{ users|rejectattr("email", "none") }}
与生成器理解类似,例如:
(u for user in users if not user.is_active) (u for user in users if not test_none(user.email))
Changelog
在 2.7 版本加入.
- replace(s: str, old: str, new: str, count: Optional[int] = None) str ¶
返回该值的副本,其中所有出现的子字符串都替换为新的子字符串。第一个参数是应该替换的子字符串,第二个参数是替换字符串。如果可选的第三个参数
count
只有第一个count
出现项被替换:{{ "Hello World"|replace("Hello", "Goodbye") }} -> Goodbye World {{ "aaaaargh"|replace("a", "d'oh, ", 2) }} -> d'oh, d'oh, aaargh
- reverse(value: Union[str, Iterable[V]]) Union[str, Iterable[V]] ¶
反转对象,或者返回一个迭代程序,该迭代程序以相反的方式对其进行迭代。
- round(value: float, precision: int = 0, method: 'te.Literal["common", "ceil", "floor"]' = 'common') float ¶
将数字四舍五入到给定的精度。第一个参数指定精度(默认为
0
,第二种取整方法:'common'
向上或向下舍入'ceil'
总是向上搜索'floor'
总是向下舍入
如果不指定方法
'common'
使用。{{ 42.55|round }} -> 43.0 {{ 42.55|round(1, 'floor') }} -> 42.5
请注意,即使舍入到0精度,也会返回一个浮点。如果你需要一个真正的整数,通过管道 int :
{{ 42.55|round|int }} -> 43
- select(value: 't.Iterable[V]', *args: Any, **kwargs: Any) 't.Iterator[V]' ¶
通过对每个对象应用测试来筛选一系列对象,并且只在测试成功后选择对象。
如果未指定测试,则每个对象都将作为布尔值进行计算。
示例用法:
{{ numbers|select("odd") }} {{ numbers|select("odd") }} {{ numbers|select("divisibleby", 3) }} {{ numbers|select("lessthan", 42) }} {{ strings|select("equalto", "mystring") }}
与生成器理解类似,例如:
(n for n in numbers if test_odd(n)) (n for n in numbers if test_divisibleby(n, 3))
Changelog
在 2.7 版本加入.
- selectattr(value: 't.Iterable[V]', *args: Any, **kwargs: Any) 't.Iterator[V]' ¶
通过对每个对象的指定属性应用测试来筛选一系列对象,并且只选择测试成功的对象。
如果未指定测试,则属性的值将作为布尔值进行计算。
示例用法:
{{ users|selectattr("is_active") }} {{ users|selectattr("email", "none") }}
与生成器理解类似,例如:
(u for user in users if user.is_active) (u for user in users if test_none(user.email))
Changelog
在 2.7 版本加入.
- slice(value: 't.Collection[V]', slices: int, fill_with: 't.Optional[V]' = None) 't.Iterator[t.List[V]]' ¶
切片迭代器并返回包含这些项的列表列表。如果要创建一个包含三个代表列的ul标记的DIV,则非常有用:
<div class="columnwrapper"> {%- for column in items|slice(3) %} <ul class="column-{{ loop.index }}"> {%- for item in column %} <li>{{ item }}</li> {%- endfor %} </ul> {%- endfor %} </div>
如果您给它传递第二个参数,它将用于在上一次迭代中填充缺少的值。
- sort(value: 't.Iterable[V]', reverse: bool = False, case_sensitive: bool = False, attribute: Union[str, int, NoneType] = None) 't.List[V]' ¶
使用Python的
sorted()
.{% for city in cities|sort %} ... {% endfor %}
- 参数
reverse -- 降序排序而不是升序排序。
case_sensitive -- 排序字符串时,请分别对大小写进行排序。
attribute -- 当对对象或指令进行排序时,要按其排序的属性或键。可以用点表示法
"address.city"
. 可以是以下属性的列表"age,name"
.
排序是稳定的,它不会改变比较相等的元素的相对顺序。这使得可以根据不同的属性和顺序进行排序。
{% for user in users|sort(attribute="name") |sort(reverse=true, attribute="age") %} ... {% endfor %}
当所有属性的方向相同时,作为链接的快捷方式,请传递一个逗号分隔的属性列表。
{% for user in users|sort(attribute="age,name") %} ... {% endfor %}
Changelog
在 2.11.0 版本发生变更: 这个
attribute
参数可以是逗号分隔的属性列表,例如。"age,name"
.在 2.6 版本发生变更: 这个
attribute
已添加参数。
- string(value)¶
如果对象尚未转换为字符串,请将其转换为字符串。这将保留一个
Markup
字符串,而不是将其转换回基本字符串,因此它仍将被标记为安全,并且不会再次转义。>>> value = escape("<User 1>") >>> value Markup('<User 1>') >>> escape(str(value)) Markup('&lt;User 1&gt;') >>> escape(soft_str(value)) Markup('<User 1>')
- sum(iterable: 't.Iterable[V]', attribute: Union[str, int, NoneType] = None, start: V = 0) V ¶
返回数字序列与参数“start”(默认值为0)的值之和。当序列为空时,它返回Start。
也可以只总结某些属性:
Total: {{ items|sum(attribute='price') }}
Changelog
在 2.6 版本发生变更: 这个
attribute
添加了参数以允许对属性进行求和。也就是start
参数被移到右侧。
- tojson(value: Any, indent: Optional[int] = None) markupsafe.Markup ¶
将对象序列化为JSON字符串,并将其标记为可以在HTML中安全呈现。此过滤仅用于Html文档。
返回的字符串在HTML文档中呈现是安全的,并且
<script>
标签。例外是在用双引号引起来的HTML属性中;可以使用单引号,也可以使用|forceescape
过滤。- 参数
value -- 要序列化为JSON的对象。
indent -- 这个
indent
传递给的参数dumps
,用于漂亮地打印价值。
Changelog
在 2.9 版本加入.
- truncate(s: str, length: int = 255, killwords: bool = False, end: str = '...', leeway: Optional[int] = None) str ¶
返回字符串的截断副本。长度由第一个参数指定,默认为
255
. 如果第二个参数是true
过滤器将剪切文本的长度。否则,它将丢弃最后一个单词。如果文本被截断,它将附加省略号 ("..."
)如果你想要一个不同的省略号"..."
您可以使用第三个参数指定它。仅超过第四个参数中给定的公差范围长度的字符串将不会被截断。{{ "foo bar baz qux"|truncate(9) }} -> "foo..." {{ "foo bar baz qux"|truncate(9, True) }} -> "foo ba..." {{ "foo bar baz qux"|truncate(11) }} -> "foo bar baz qux" {{ "foo bar baz qux"|truncate(11, False, '...', 0) }} -> "foo bar..."
新的Jinja版本的默认余地是5,以前是0,但可以全局重新配置。
- unique(value: 't.Iterable[V]', case_sensitive: bool = False, attribute: Union[str, int, NoneType] = None) 't.Iterator[V]' ¶
返回给定iterable中唯一项的列表。
{{ ['foo', 'bar', 'foobar', 'FooBar']|unique|list }} -> ['foo', 'bar', 'foobar']
唯一项的生成顺序与传递给筛选器的iterable中第一次出现的顺序相同。
- 参数
case_sensitive -- 将大小写字符串视为不同的字符串。
attribute -- 为此属性筛选具有唯一值的对象。
- urlencode(value: Union[str, Mapping[str, Any], Iterable[Tuple[str, Any]]]) str ¶
引用数据以便在URL路径或使用UTF-8的查询中使用。
基本包装
urllib.parse.quote()
如果给了一个字符串,或者urllib.parse.urlencode()
为了一个口述或一个可写的。- 参数
value -- 要引用的数据。字符串将被直接引用。口述
(key, value)
对将作为查询字符串联接。
当给定字符串时,“/”不加引号。HTTP服务器在路径中等价地处理“/”和“%2F”。如果需要引用斜杠,请使用
|replace("/", "%2F")
过滤器。Changelog
在 2.7 版本加入.
- urlize(value: str, trim_url_limit: Optional[int] = None, nofollow: bool = False, target: Optional[str] = None, rel: Optional[str] = None, extra_schemes: Optional[Iterable[str]] = None) str ¶
将文本中的URL转换为可点击的链接。
在某些情况下,这可能无法识别链接。通常,更全面的格式化程序(如Markdown库)是更好的选择。
工作于
http://
,https://
,www.
,mailto:
和电子邮件地址。带有尾随标点符号(句点、逗号、右括号)和前导标点符号(左括号)的链接将被识别,但不包括标点符号。不识别包括报头字段的电子邮件地址(例如,mailto:address@example.com?cc=copy@example.com
)。- 参数
value -- 包含要链接的URL的原始文本。
trim_url_limit -- 将显示的URL值缩短到此长度。
nofollow -- 添加
rel=nofollow
属性添加到链接。target -- 添加
target
属性添加到链接。rel -- 添加
rel
属性添加到链接。extra_schemes -- 除了默认行为之外,还可以识别以这些方案开头的URL。默认为
env.policies["urlize.extra_schemes"]
,它默认为没有额外的方案。
Changelog
在 3.0 版本发生变更: 这个
extra_schemes
参数已添加。在 3.0 版本发生变更: 生成
https://
没有方案的URL链接。在 3.0 版本发生变更: 解析规则已更新。识别电子邮件地址,无论是否使用
mailto:
计划。验证IP地址。在更多情况下忽略圆括号和方括号。在 2.8 版本发生变更: 这个
target
参数已添加。
- wordwrap(s: str, width: int = 79, break_long_words: bool = True, wrapstring: Optional[str] = None, break_on_hyphens: bool = True) str ¶
将字符串按给定宽度换行。现有换行符被视为要单独包装的段落。
- 参数
s -- 要换行的原始文本。
width -- 包装线的最大长度。
break_long_words -- 如果一个单词比
width
,把它分开。break_on_hyphens -- 如果一个单词包含连字符,它可以被拆分成多行。
wrapstring -- 连接每个换行符的字符串。默认为
Environment.newline_sequence
.
Changelog
在 2.11 版本发生变更: 现有换行符被视为单独包装的段落。
在 2.11 版本发生变更: 增加了
break_on_hyphens
参数。在 2.7 版本发生变更: 增加了
wrapstring
参数。
- xmlattr(d: Mapping[str, Any], autospace: bool = True) str ¶
基于dict中的项创建sgml/xml属性字符串。所有值都不是 none 也不 undefined 自动转义:
<ul{{ {'class': 'my_list', 'missing': none, 'id': 'list-%d'|format(variable)}|xmlattr }}> ... </ul>
结果是这样的:
<ul class="my_list" id="list-42"> ... </ul>
如您所见,如果过滤器返回某些内容,除非第二个参数为false,否则它会自动在项目前面预留一个空格。
内置测试列表¶
- callable(obj, /)¶
返回对象是否可调用(即某种函数)。
请注意,类是可调用的,使用uuu call_uu()方法的类的实例也是可调用的。
- defined(value: Any) bool ¶
如果定义了变量,则返回true:
{% if variable is defined %} value of variable: {{ variable }} {% else %} variable is not defined {% endif %}
见
default()
筛选以获取设置未定义变量的简单方法。
- eq(a, b, /)¶
与a==b相同。
- 别名
==
,equalto
- filter(value: str) bool ¶
按名称检查是否存在过滤。如果可能有过滤可选,则非常有用。
{% if 'markdown' is filter %} {{ value | markdown }} {% else %} {{ value }} {% endif %}
Changelog
在 3.0 版本加入.
- ge(a, b, /)¶
与a>=b相同。
- 别名
>=
- gt(a, b, /)¶
与a>b相同。
- 别名
>
,greaterthan
- le(a, b, /)¶
与a<=b相同。
- 别名
<=
- lt(a, b, /)¶
与a<b相同。
- 别名
<
,lessthan
- ne(a, b, /)¶
和a一样!=b。
- 别名
!=
- sameas(value: Any, other: Any) bool ¶
检查一个对象是否指向与另一个对象相同的内存地址:
{% if foo.attribute is sameas false %} the foo attribute really is the `False` singleton {% endif %}
全局函数列表¶
默认情况下,以下函数在全局范围内可用:
- range([start, ]stop[, step])¶
返回包含整数算术级数的列表。
range(i, j)
收益率[i, i+1, i+2, ..., j-1]
开始(!)默认为0
. 当给定步骤时,它指定增量(或减量)。例如,range(4)
和range(0, 4, 1)
返回[0, 1, 2, 3]
. 省略了终点!这正是4个元素列表的有效索引。这对于多次重复模板块很有用,例如填充列表。假设列表中有7个用户,但您希望呈现三个空项以使用css强制高度:
<ul> {% for user in users %} <li>{{ user.username }}</li> {% endfor %} {% for number in range(10 - users|count) %} <li class="empty"><span>...</span></li> {% endfor %} </ul>
- lipsum(n=5, html=True, min=20, max=100)¶
为模板生成一些lorem ipsum。默认情况下,将生成5段HTML,每个段落的长度介于20到100个单词之间。如果html为false,则返回常规文本。这对于生成布局测试的简单内容很有用。
- dict(\**items)¶
听写文字的一种方便的替代方法。
{{'foo': 'bar'}}
是一样的dict(foo='bar')
.
- class cycler(\*items)¶
通过一次生成一个值来循环遍历这些值,然后在到达终点后重新启动。
类似
loop.cycle
,但可以在循环外部或多个循环之间使用。例如,在列表中呈现文件夹和文件的列表,交替为它们提供“奇数”和“偶数”类。{% set row_class = cycler("odd", "even") %} <ul class="browser"> {% for folder in folders %} <li class="folder {{ row_class.next() }}">{{ folder }} {% endfor %} {% for file in files %} <li class="file {{ row_class.next() }}">{{ file }} {% endfor %} </ul>
- 参数
items -- 每个位置参数将按照每个循环给定的顺序生成。
Changelog
在 2.1 版本加入.
- reset()¶
将当前项重置为第一项。
- class joiner(sep=', ')¶
一个可以用来“连接”多个部分的小助手。一个连接符被传递一个字符串,每次调用它时都会返回该字符串,除了第一次(在这种情况下,它返回一个空字符串)。你可以用它来连接事物:
{% set pipe = joiner("|") %} {% if categories %} {{ pipe() }} Categories: {{ categories|join(", ") }} {% endif %} {% if author %} {{ pipe() }} Author: {{ author() }} {% endif %} {% if can_edit %} {{ pipe() }} <a href="?action=edit">Edit</a> {% endif %}
Changelog
在 2.1 版本加入.
- class namespace(...)¶
创建一个新容器,该容器允许使用
{{% set %}}
标签:{% set ns = namespace() %} {% set ns.foo = 'bar' %}
其主要目的是允许将值从循环体内部传递到外部范围。初始值可以作为dict、关键字参数或两者都提供(与python的行为相同) dict 构造函数::
{% set ns = namespace(found=false) %} {% for item in items %} {% if item.check_something() %} {% set ns.found = true %} {% endif %} * {{ item.title }} {% endfor %} Found item having something: {{ ns.found }}
Changelog
在 2.10 版本加入.
扩展¶
以下部分介绍应用程序可能启用的内置Jinja扩展。应用程序还可以提供本文档未涵盖的进一步扩展;在这种情况下,应该有一个单独的文档解释 extensions .
i18n¶
如果 i18n扩展 则可以将模板中的文本标记为可翻译。若要将节标记为可翻译,请使用 trans
挡路:
{% trans %}Hello, {{ user }}!{% endtrans %}
在块内部,不允许使用语句,只允许文本和简单变量标记。
变量标记只能是名称,不能是属性访问、筛选器或其他表达式。若要使用表达式,请将其绑定到 trans
在块中使用的标记。
{% trans user=user.username %}Hello, {{ user }}!{% endtrans %}
若要绑定多个表达式,请使用逗号分隔每个表达式 (,
)
{% trans book_title=book.title, author=author.name %}
This is {{ book_title }} by {{ author }}
{% endtrans %}
要复数形式,请指定用 pluralize
标签。
{% trans count=list|length %}
There is {{ count }} {{ name }} object.
{% pluralize %}
There are {{ count }} {{ name }} objects.
{% endtrans %}
默认情况下,块中的第一个变量用于确定是使用单数形式还是复数形式。如果不正确,请指定用于复数形式的变量作为 pluralize
.
{% trans ..., user_count=users|length %}...
{% pluralize user_count %}...{% endtrans %}
翻译文本块时,空格和换行符会导致翻译字符串难以阅读且容易出错。为了避免这种情况,可以将trans块标记为trimmed,这将用一个空格替换所有换行符及其周围的空白,并删除前导空格和尾随空格。
{% trans trimmed book_title=book.title %}
This is {{ book_title }}.
You should read it!
{% endtrans %}
这导致 This is %(book_title)s. You should read it!
在翻译文件中。
如果全局启用剪裁,则 notrimmed
修饰符可用于禁用块。
Changelog
在 2.10 版本加入: 这个 trimmed
和 notrimmed
已添加修饰符。
可以使用以下函数转换表达式中的字符串:
gettext
:转换单个字符串ngettext
:转换可复数字符串_
: alias forgettext
您可以像这样打印字符串:
{{ _("Hello, World!") }}
要使用占位符,请使用 format
过滤器。
{{ _("Hello, %(user)s!")|format(user=user.username) }}
始终使用关键字参数 format
,因为其他语言可能不使用相同顺序的单词。
如果 新样式Gettext 调用被激活,使用占位符更容易。格式化是 gettext
调用而不是使用 format
过滤器。
{{ gettext('Hello World!') }}
{{ gettext('Hello %(name)s!', name='World') }}
{{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
这个 ngettext
函数的格式字符串自动将计数作为 num
除给定参数外的参数。
表达式语句¶
如果已加载表达式语句扩展名,则调用 do 与正则变量表达式的工作方式完全相同 ({{{{ ... }}}}
)但它什么都不打印。这可用于修改列表:
{% do navigation.append('a string') %}
循环控制¶
如果应用程序启用 循环控制 ,可以使用 break 和 continue 在循环中。什么时候? break 到达时,循环终止;如果 continue 到达时,停止处理并继续下一次迭代。
这里有一个循环,每秒钟跳过一项:
{% for user in users %}
{%- if loop.index is even %}{% continue %}{% endif %}
...
{% endfor %}
同样,在第10次迭代后停止处理的循环:
{% for user in users %}
{%- if loop.index >= 10 %}{% break %}{% endif %}
{%- endfor %}
注意 loop.index
从1开始,然后 loop.index0
以0开头(请参见: 为了 )
调试语句¶
如果 调试扩展 已启用,a {{% debug %}}
标记将可用于转储当前上下文以及可用的筛选器和测试。这对于在不设置调试器的情况下查看模板中可使用的内容非常有用。
<pre>{% debug %}</pre>
{'context': {'cycler': <class 'jinja2.utils.Cycler'>,
...,
'namespace': <class 'jinja2.utils.Namespace'>},
'filters': ['abs', 'attr', 'batch', 'capitalize', 'center', 'count', 'd',
..., 'urlencode', 'urlize', 'wordcount', 'wordwrap', 'xmlattr'],
'tests': ['!=', '<', '<=', '==', '>', '>=', 'callable', 'defined',
..., 'odd', 'sameas', 'sequence', 'string', 'undefined', 'upper']}
附有声明¶
Changelog
在 2.3 版本加入.
WITH语句使创建新的内部范围成为可能。在此范围内设置的变量在范围外不可见。
简而言之:
{% with %}
{% set foo = 42 %}
{{ foo }} foo is 42 here
{% endwith %}
foo is not visible here any longer
因为在范围的开始设置变量是很常见的,所以可以在 with 语句。以下两个示例是等效的:
{% with foo = 42 %}
{{ foo }}
{% endwith %}
{% with %}
{% set foo = 42 %}
{{ foo }}
{% endwith %}
关于范围界定的重要说明。在2.9之前的Jinja版本中,将一个变量引用到另一个变量的行为会产生一些意想不到的后果。尤其是,一个变量可以引用在同一with block的opening语句中定义的另一个变量。这导致了清理范围行为的问题,并已得到改进。特别是在较新的Jinja版本中,下面的代码总是引用变量 a 从外面 with 块::
{% with a={}, b=a.attribute %}...{% endwith %}
在早期的Jinja版本中, b 属性将引用第一个属性的结果。如果您依赖于此行为,则可以重写它以使用 set
标签:
{% with a={} %}
{% set b = a.attribute %}
{% endwith %}
延伸
在旧版本的Jinja(2.9之前)中,需要通过扩展来启用此功能。它现在默认启用。
自动转义重写¶
Changelog
在 2.4 版本加入.
如果需要,可以从模板中激活和停用自动转义。
例子::
{% autoescape true %}
Autoescaping is active within this block
{% endautoescape %}
{% autoescape false %}
Autoescaping is inactive within this block
{% endautoescape %}
后一 endautoescape 这种行为会恢复到以前的状态。
延伸
在旧版本的Jinja(2.9之前)中,需要通过扩展来启用此功能。它现在默认启用。