模板设计人员的文档

本文档描述模板引擎的语法和语义,它对于创建 Jinja 模板的人员作为参考将是最有用的。 由于模板引擎非常灵活,因此应用的配置与此处提供的代码在分隔符和未定义值的行为方面可能略有不同。

概要

Jinja 模板只是一个文本文件。 Jinja 可以生成任何基于文本的格式(HTML、XML、CSV、LaTeX 等)。 Jinja 模板不需要有特定的扩展名:.html.xml 或其它任何扩展名都可以。

模板包含变量​​和/或表达式,当渲染模板时,它们将被替换为具体的值;模板还包含标签,它们控制模板的逻辑。 模板语法深受 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 分隔符配置如下:

  • {% ... %} 用于语句

  • {{ ... }} 用于表达式,它直接打印到模板输出

  • {# ... #} 用于注释,它不包含在模板输出中

  • #  ... ## 用于行语句

模板文件扩展名

如上所述,任何文件都可以作为模板加载,而不考虑文件扩展名。 添加 .jinja 扩展名如 user.html.jinja 可能会使某些 IDE 或编辑器插件更容易识别,但不是必需的。 稍后引入的自动转义可以基于文件扩展名应用,因此在这种情况下需要考虑额外的后缀。

识别模板的另一个好启发是,它们位于templates文件夹中,而不考虑扩展。 这是项目的常见布局。

变量

模板变量由传递到模板的上下文字典定义。

模板中的变量由应用程序传入,你可能把它们弄得混乱。 你还可以访问变量的属性或元素。 变量具有哪些属性在很大程度上取决于提供该变量的应用程序。

除了标准的 Python __getitem__下标语法([]),你还可以使用点(.)访问变量的属性。

以下行执行相同的操作:

{{ foo.bar }}
{{ foo['bar'] }}

请务必知道,外部双大括号不是变量的一部分,而是打印语句的一部分。 如果访问标记中的变量,请不要在标记周围放置大括号。

如果变量或属性不存在,您将返回未定义的值。 对此类值可以执行的操作取决于应用程序配置:默认行为是计算为空字符串(如果打印或迭代),并且所有其他操作都失败。

实现

为方便起见,Jinja 中的foo.bar在 Python 层上执行以下操作:

  • 检查foo上称为bar的属性(getattr(foo,"bar")

  • 如果没有,请检查foo foo.__getitem__('bar')中的项目'bar'

  • 如果没有,则返回未定义的对象。

foo['bar']的工作方式大致相同,顺序差异很小:

  • 检查foo中的项目'bar' foo.__getitem__('bar')

  • 如果没有,请检查foo上称为bar的属性。 ("酒吧")

  • 如果没有,则返回未定义的对象。

如果对象具有具有相同名称的项和属性,则这一点很重要。 此外attr()筛选器仅查找属性。

Filters

变量可以通过 filters 修改。 Filters 由管道符号(|)与变量分隔,且可以带有括号和可选参数。 可以链接多个 filter。 一个 filter 的输出应用于下一个 filter。

例如 {{ name|striptags|title }} 将删除变量 name 中所有的 HTML 标记,并 title-case 输出(title(striptags(name)))。

接受参数的 filter 在参数周围有括号,就像函数调用一样。 例如:{{ listx|join(', ') }} 将用逗号连接一个列表(str.join(', ', listx))。

下面的List of Builtin Filters描述了所有内置筛选器。

测试|

除了过滤器,还有所谓的"测试"可用。 测试可用于针对公共表达式测试变量。 要测试变量或表达式,添加变量之后的测试名称。 例如,为了确定是否定义了变量,可以执行名称定义,然后根据是否在当前模板上下文中定义名称,返回 true 或 false。

测试也可以接受参数。 如果测试只采用一个参数,则可以排除括号。 例如,以下两个表达式执行相同的操作:

{% if loop.index is divisibleby 3 %}
{% if loop.index is divisibleby(3) %}

下面的List of Builtin Tests描述了所有内置测试。

注释

要注释出模板中行的一部分,请使用注释语法,默认情况下设置为 {# ... #}. 这对于注释出模板的某些部分以进行调试或为其他模板设计人员或您自己添加信息非常有用:

{# note: commented-out template because we no longer use this
    {% for user in users %}
        ...
    {% endfor %}
#}

空白控制|

在默认配置中:

  • 如果存在,将剥离单个尾随条带

  • 其他空白(空格、选项卡、符线等)返回不变

如果应用程序将 Jinja 配置为trim_blocks,则模板标记后的第一个行将自动删除(如 PHP 中)。 lstrip_blocks选项还可以设置为从行开始到块的开头剥离制表符和空格。 (如果块开始之前有其他字符,则不会剥离任何字符。

启用trim_blockslstrip_blocks后,可以将块标记放在自己的行上,渲染时将删除整个块行,从而保留内容的空白。 例如,如果没有trim_blockslstrip_blocks选项,则此模板:

<div>
    {% if True %}
        yay
    {% endif %}
</div>

使用 div 内的空白行进行渲染:

<div>

        yay

</div>

但是,启用trim_blockslstrip_blocks后,将删除模板块行并保留其他空白:

<div>
        yay
</div>

您可以通过在块的开头放置加号 (+) 来手动禁用lstrip_blocks行为:

<div>
        {%+ if something %}yay{% endif %}
</div>

您还可以手动剥离模板中的空白。 如果向块的开头或结尾(例如For标记)、注释或变量表达式添加减号 (-),则该块之前或之后的空白将被删除:

{% for item in seq -%}
    {{ item }}
{%- endfor %}

这将生成它们之间没有空格的所有元素。 如果seq19的数字列表,则输出将为123456789

如果启用Line Statements,它们会自动从行的开头剥离前导空格。

默认情况下,Jinja 还会删除尾随的条线。 要保留单条尾随条,请将金雅配置为keep_trailing_newline。

注意

不得在标记和减号之间添加空格。

有效

{%- if foo -%}...{% endif %}

无效

{% - if foo - %}...{% endif %}

转义

有时,让 Jinja 忽略它本来会作为变量或块处理的部件是可取的,甚至是必要的。 例如,如果使用默认语法,您希望{{用作模板中的原始字符串,而不是启动变量,则必须使用技巧。

输出文本变量分隔符 ({{} ) 的最简单方法是使用变量表达式:

{{ '{{' }}

对于较大的部分,将块标记为原始是有意义的。 例如,要在模板中包含示例 Jinja 语法,可以使用此代码段:

{% raw %}
    <ul>
    {% for item in seq %}
        <li>{{ item }}</li>
    {% endfor %}
    </ul>
{% endraw %}

注意

[% 原始 -%]标记末尾的减号将清除原始数据第一个字符前面的所有空格和行符。

行语句

如果应用程序启用了行语句,则可以将行标记为语句。 例如,如果 line 语句前缀配置为#则以下两个示例等效:

<ul>
# for item in seq
    <li>{{ item }}</li>
# endfor
</ul>

<ul>
{% for item in seq %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

只要行前没有任何文本,行语句前缀就可以出现在行的任意位置。 为了更好地可读性,启动块的语句(如if 、elif等)可能以冒号结尾:

# for item in seq:
    ...
# endfor

注意

如果存在打开的括号、大括号或括号,则行语句可以跨多行:

<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

模板继承

金贾最强大的部分是模板继承。 模板继承允许您构建一个基本"骨架"模板,该模板包含网站的所有公共元素,并定义子模板可以覆盖的

听起来很复杂,但很基本。 从示例开始是最容易理解的。

基本模板|

这个模板,我们将称为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 %}
        &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>.
        {% endblock %}
    </div>
</body>
</html>

在此示例中,[% %]标记定义子模板可以填写的四个块。 所有块标记所做的是告诉模板引擎子模板可能会覆盖模板中的这些占位符。

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 %}

{% 扩展 %_ 标记是此处的键。 它告诉模板引擎此模板"扩展"另一个模板。 当模板系统评估此模板时,它首先找到父模板。 扩展标记应为模板中的第一个标记。 一切在打印前正常打印出来,可能会导致混乱。 有关此行为以及如何利用此行为的详细信息,请参阅Null-Master Fallback 此外,无论周围条件被评估为真还是假,始终都会填充块。

模板的文件名取决于模板加载程序。 例如FileSystemLoader允许您通过提供文件名来访问其他模板。 您可以使用斜杠访问子目录中的模板:

{% extends "layout/default.html" %}

但是,此行为可能取决于嵌入 Jinja 的应用程序。 请注意,由于子模板不定义footer块,因此将改用父模板中的值。

不能在同一模板中定义多个具有相同名称的{% %]标记。 存在此限制是因为块标记在"两个"方向上工作。 也就是说,块标记不仅提供要填充的占位符 - 它还定义填充项中占位符的内容。 如果模板中有两个名称类似的{% %]标记,则该模板的父级将不知道要使用的块内容之一。

但是,如果要多次打印块,可以使用特殊的self变量并使用该名称调用块:

<title>{% block title %}{% endblock %}</title>
<h1>{{ self.title() }}</h1>
{% block body %}{% endblock %}

超级方块|

可以通过调用super()来呈现父块的内容。 这将返回父块的结果:

{% block sidebar %}
    <h3>Table Of Contents</h3>
    ...
    {{ super() }}
{% endblock %}

嵌套扩展|

在多个级别[% 扩展 %]的情况下,可以链接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将给予 身体: 你好 孩子。 你好 父母。

渲染grandchild1.tmpl将给 身体: 你好 孙子1。

渲染grandchild2.tmpl将给 身体: 你好 孙子2。 你好 父母。

命名块结束标记|

Jinja 允许您在结束标记后放置块的名称,以便更好地可读性:

{% block sidebar %}
    {% block inner_sidebar %}
        ...
    {% endblock inner_sidebar %}
{% endblock sidebar %}

但是,终结点块单词后的名称必须与块名称匹配。

块嵌套和范围|

可以为更复杂的布局嵌套块。 但是,每个默认块可能无法从外部作用域访问变量:

{% for item in seq %}
    <li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}

此示例将输出空<li>项,因为项目在块内不可用。 这样做的原因是,如果块被子模板替换,就会出现未在块中定义或传递给上下文的变量。

从 Jinja 2.2 开始,可以通过将作用域修饰符添加到块声明将块设置为"范围",可以显式指定块中可用的变量:

{% for item in seq %}
    <li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
{% endfor %}

重写块时,不必提供作用域修饰符。

模板对象|

更改日志

在版本 2.4 中更改。

如果在模板上下文中传递了模板对象,也可以从该对象进行扩展。 假设调用代码将布局模板作为layout_template环境传递,则此代码工作正常:

{% extends layout_template %}

以前,layout_template变量必须是具有布局模板的文件名的字符串才能正常工作。

HTML 转义|

从模板生成 HTML 时,始终存在变量包含影响生成的 HTML 的字符的风险。 有两种方法:

  1. 手动转义每个变量;或

  2. 默认情况下自动转义所有内容。

金雅支持两者。 使用的内容取决于应用程序配置。 默认配置不是自动转义;由于各种原因:

  • 除安全值外,要逃逸所有内容也意味着 Jinja 正在逃避已知不包括 HTML 的变量(例如数字、布尔值),这可能是一个巨大的性能冲击。

  • 有关变量安全性的信息非常脆弱。 通过强制使用安全和不安全值,返回值可能是双转义 HTML。

使用手动转出|

如果启用了手动转义,则您有责任根据需要转义变量。 什么可以逃避? 如果您有一个变量,其中可能包含以下任何字符> < &、 或"转义它,除非该变量包含格式良好且受信任的 HTML。 通过|e筛选器将变量管道化,可进行逃逸工作:

{{ user.username|e }}

使用自动转义

启用自动转义时,默认情况下,除了显式标记为安全的值外,所有内容都转义。 变量和表达式可以在:

  1. 具有标记安全的应用程序的上下文字典markupsafe.Markup

  2. 带有|safe筛选器的模板。

如果标记为安全的字符串通过其他不懂该标记的 Python 代码传递,则该字符串可能会丢失。 在到达模板之前,请注意数据何时被标记为安全,以及数据的处理方式。

如果值已转义但未标记为安全,则将自动转义仍将发生,并导致双转义字符。 如果您知道数据已经安全但未标记,请确保将其包装在Markup中或使用|safe筛选器。

金贾功能(宏,超级自我。BLOCKNAME) 始终返回标记为安全的模板数据。

具有自动转义的模板中的字符串文本被认为是不安全的,因为本机 Python 字符串strbasestring)不是MarkupSafe.标记字符串,具有__html__属性。 unicode

控制结构列表|

控制结构是指控制程序流的所有事物 - 条件(即 if/elif/else)、对于循环,以及宏和块等内容。 使用默认语法,控件结构将显示在内部 {% ... %} 块。

For

循环访问序列中的每个项。 例如,要显示在名为"用户"的变量中提供的用户列表:

<h1>Members</h1>
<ul>
{% for user in users %}
  <li>{{ user.username|e }}</li>
{% endfor %}
</ul>

由于模板中的变量保留其对象属性,因此可以迭代容器,如听写

<dl>
{% for key, value in my_dict.items() %}
    <dt>{{ key|e }}</dt>
    <dd>{{ value|e }}</dd>
{% endfor %}
</dl>

但是请注意,Python 的听写不是订购的,但是,Python 的听写不是订购的。因此,您可能希望传递已排序的tuplelistcollections.OrderedDict = 到模板,或使用听写筛选器。

在 for 循环块中,可以访问一些特殊变量:

变量

描述

loop.index

循环的当前迭代。 (1 索引)

loop.index0

循环的当前迭代。 (0 索引)

loop.revindex

循环末尾的迭代次数(1 索引)

loop.revindex0

循环末尾的迭代次数(0 索引)

loop.first

如果第一次迭代,则为 True。

loop.last

如果上次迭代为 True。

loop.length

序列中的项数。

loop.cycle

用于在序列列表之间循环的帮助函数。 请参阅下面的说明。

loop.depth

指示呈现当前在递归循环中的深度。 从级别 1 开始

loop.depth0

指示呈现当前在递归循环中的深度。 从级别 0 开始

loop.previtem

循环上一个迭代中的项。 在第一次迭代期间未定义。

loop.nextitem

循环的后续迭代中的项。 上次迭代期间未定义。

loop.changed(*val)

如果以前调用的值不同(或根本不调用),则为 True。

在 for 循环中,可以使用特殊循环。循环帮助程序:每次在循环中循环字符串/变量列表之间循环:

{% for row in rows %}
    <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}

自 Jinja 2.1 以来,存在一个额外的循环助手,允许循环未绑定循环。 有关详细信息,请查看List of Global Functions

与 Python 不同,不可能在循环中中断继续 但是,您可以在迭代期间筛选序列,这允许您跳过项。 以下示例跳过所有隐藏的用户:

{% for user in users if not user.hidden %}
    <li>{{ user.username|e }}</li>
{% endfor %}

优点是特殊循环变量将正确计数;因此,不计算用户不迭代。

如果由于序列为空或筛选从序列中删除所有项而未进行迭代,则可以使用其他呈现默认块:

<ul>
{% for user in users %}
    <li>{{ user.username|e }}</li>
{% else %}
    <li><em>no users found</em></li>
{% endfor %}
</ul>

请注意,在 Python 中,当相应的循环中断时,将执行其他块。 由于 Jinja 循环无论如何都无法中断,因此选择了else关键字略有不同的行为。

也可以递归使用循环。 如果您正在处理递归数据(如站点地图或 RDFa),则此功能非常有用。 要递归使用循环,基本上必须将递归修饰符添加到循环定义中,并使用要递归的新可迭代位置调用循环变量。

下面的示例实现具有递归循环的站点映射:

<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>

循环变量始终引用最近(最内侧)循环。 如果我们有多个级别的循环,我们可以在我们想要以递归方式使用的循环之后编写[%集outer_loop = 循环 %]来重新绑定变量循环 然后,我们可以调用它使用{ outer_loop(...) |

请注意,循环中的分配将在迭代结束时清除,并且不能比循环范围活得多。 旧版本的Jinja有一个错误,在某些情况下,似乎任务会工作。 不支持此功能。 有关如何处理此问题的详细信息,请参阅Assignments

如果只想检查自上次迭代以来某些值是否已更改,或者在下一次迭代中是否已更改,则可以使用前项下一项

{% 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 %}

如果您只关心值是否更改,则使用更改会更容易:

{% for entry in entries %}
    {% if loop.changed(entry.category) %}
        <h2>{{ entry.category }}</h2>
    {% endif %}
    <p>{{ entry.message }}</p>
{% endfor %}

If

Jinja 中的if语句可与 Python if 语句进行比较。 在最简单的形式中,可以使用它来测试变量是否定义,不是空的,而不是 false 的:

{% if users %}
<ul>
{% for user in users %}
    <li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}

对于多个分支,elif 可以像在 Python 中使用。 您也可以在那里使用更复杂的Expressions

{% if kenny.sick %}
    Kenny is sick.
{% elif kenny.dead %}
    You killed Kenny!  You bastard!!!
{% else %}
    Kenny looks okay --- so far
{% endif %}

如果也可以用作inline expressionloop filtering

Macros

宏与常规编程语言中的函数类似。 它们可用于将常用的习语转换为可重用的函数,以便不重复自己("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

如果宏接受额外的关键字参数(即:访问特殊的kwargs变量),则为 true。

catch_varargs

如果宏接受额外的位置参数(即:访问特殊的varargs变量),则为 true。

caller

如果宏访问特殊调用方变量,并且可能从call标记调用,则为 true。

如果宏名称以下划线开头,则不会导出,无法导入。

调用

在某些情况下,将宏传递到另一个宏可能很有用。 为此,您可以使用特殊调用块。 下面的示例显示了利用调用功能以及如何使用它的宏:

{% 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>
        <dl>Realname</dl>
        <dd>{{ user.realname|e }}</dd>
        <dl>Description</dl>
        <dd>{{ user.description }}</dd>
    </dl>
{% endcall %}

过滤器|

筛选器部分允许您对模板数据块应用常规的 Jinja 筛选器。 只需在特殊筛选器部分中包装代码:

{% filter upper %}
    This text becomes uppercase
{% endfilter %}

赋值

在代码块中,还可以为变量分配值。 顶层分配(块、宏或循环之外)从模板(如顶级宏)导出,并可以由其他模板导入。

分配使用设置标记,可以有多个目标:

{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
{% set key, value = call_something() %}

范围行为

请记住,不可能在块内设置变量,并使它们显示在块之外。 这也适用于循环。 该规则的唯一例外是,如果语句不引入作用域。 因此,以下模板不会执行您所期望的:

{% set iterated = false %}
{% for item in seq %}
    {{ item }}
    {% set iterated = true %}
{% endfor %}
{% if not iterated %} did not iterate {% endif %}

使用 Jinja 语法无法执行此操作。 而是使用替代构造,如循环其他块或特殊循环变量:

{% 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表示法仅允许命名空间对象;试图在任何其他对象上分配属性将引发异常。

更改日志

版本 2.10 中的新增功能: 添加了对命名空间对象的支持

块分配|

更改日志

版本 2.8 中新增。

从 Jinja 2.8 开始,还可以使用块赋值将块的内容捕获到变量名称中。 这在某些情况下可用作宏的替代方法。 在这种情况下,您只编写变量名称,然后捕获所有内容,直到[% 结束集 %]。

例子:

{% set navigation %}
    <li><a href="/">Index</a>
    <li><a href="/downloads">Downloads</a>
{% endset %}

然后,导航变量包含导航 HTML 源。

更改日志

在版本 2.10 中更改。

从 Jinja 2.10 开始,块分配支持筛选器。

例子:

{% set reply | wordwrap %}
    You wrote:
    {{ message }}
{% endset %}

Extends

扩展标记可用于从另一个模板扩展一个模板。 文件中可以有多个扩展标记,但一次只能执行其中一个扩展标记。

请参阅上面有关Template Inheritance的部分。

|

块用于继承,并同时充当占位符和替换。 它们在Template Inheritance部分中详细记录。

Include

包含标记可用于包含模板并将该文件的呈现内容返回到当前命名空间:

{% include 'header.html' %}
    Body
{% include 'footer.html' %}

默认情况下,包含的模板可以访问活动上下文的变量。 有关导入和包含的上下文行为的更多详细信息,请参阅Import Context Behavior

从金贾2.2开始,你可以标记一个包含忽略缺失;在这种情况下,如果要包含的模板不存在,Jinja 将忽略该语句。 with上下文结合使用时,必须将其放在上下文可见性语句之前 下面是一些有效示例:

{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
更改日志

版本 2.2 中的新增功能。

您还可以提供在包含之前检查是否存在的模板列表。 将包含存在的第一个模板。 如果给出忽略缺失,则如果不存在任何模板,它将回退到不呈现任何内容,否则将引发异常。

例子:

{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
更改日志

在版本 2.4 中更改: 如果模板对象已传递到模板上下文,则可以使用包括包含 的对象。

导入|

Jinja 支持将常用的代码放入宏中。 这些宏可以进入不同的模板,并从那里导入。 这与 Python 中的导入语句类似。 请务必知道导入是缓存的,并且导入的模板无法访问当前模板变量,默认情况下只有全局变量。 有关导入和包含的上下文行为的更多详细信息,请参阅Import Context Behavior

有两种方法可以导入模板。 您可以将完整模板导入到变量中,或请求特定的宏/导出变量。

想象一下,我们有一个帮助器模块来呈现表单(称为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>

以一个或多个下划线开头的宏和变量是私有的,不能导入。

更改日志

在版本 2.4 中更改: 如果模板对象已传递到模板上下文,则可以从该对象导入。

导入上下文行为|

默认情况下,包含的模板传递当前上下文,导入的模板不传递。 原因是,与包含不同,导入被缓存;由于导入通常用作包含宏的模块。

可以显式更改此行为:通过添加上下文不包含上下文到导入/包含指令,可以将当前上下文传递给模板并自动禁用缓存。

下面是两个示例:

{% from 'forms.html' import input with context %}
{% include 'header.html' without context %}

注意

在 Jinja 2.0 中,传递给包含的模板的上下文不包括模板中定义的变量。 事实上,这不起作用:

{% for box in boxes %}
    {% include "render_box.html" %}
{% endfor %}

随附的模板render_box.html 无法访问Jinja 2.0 中的 自金贾2.1,render_box.htmlrender_box.html能够做到这一点。

表达式|

金雅允许在任何地方的基本表达。 这些工作与常规 Python 非常相似;即使您不使用 Python,您也应该对此感到自在。

字面值

最简单的表达式形式是文本。 文本是 Python 对象的表示形式,如字符串和数字。 存在以下文本:

"Hello World"

两个双引号或单引号之间的所有内容都是一个字符串。 每当您需要模板中的字符串时(例如,作为函数调用和筛选器的参数,或者只是扩展或包含模板),它们都很有用。

42 / 123_456

整数是没有小数部分的整数。 "*"字符可用于分隔组,以便易读性。

42.23 / 42.1e2 / 123_456.789

浮动点数可以用"."作为十进制标记书写。 它们也可以用科学记数法书写,大写或小写"e"来表示指数部分。 "*"字符可用于分隔组,以便易读性,但不能在指数部分中使用。

['list', 'of', 'objects']

两个括号之间的一切都是列表。 列表可用于存储要迭代的顺序数据。 例如,您可以使用 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用于扩展到被视为错误的未定义的变量),因此现在也可以在标题大小写(True、false)中编写。 但是,为了一致性,(所有 Jinja 标识符都是小写)您应该使用小写版本。

数学|

Jinja 允许您使用值进行计算。 这在模板中很少有用,但出于完整性的考虑而存在。 支持以下运算符:

+

将两个对象相加。 通常对象是数字,但如果两者都是字符串或列表,则可以以这种方式将它们串联。 但是,这不是串联字符串的首选方式! 对于字符串串联,请查看~运算符。 { 1 } 1 } = 2 。 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 forif表达式,组合多个表达式非常有用:

and

如果左侧和右侧操作数为 true,则返回 true。

or

如果左侧或右侧操作数为 true,则返回 true。

not

否定语句(见下文)。

(expr)

括号对表达式进行分组。

注意

isin运算符支持否定使用内缀符号,太: foo 不是 barfoo 不在 bar 而不是 foo bar,而不是 foobar 所有其他表达式都需要前缀表示法: (福 条形)。

其它运算符

以下运算符非常有用,但不适合其他两个类别中的任何一个:

in

执行序列/映射包含测试。 如果左侧操作数包含在右侧,则返回 true。 例如,{1、2、3} 中的 1将返回 true。

is

执行test

|

应用filter

~

将所有操作数转换为字符串并串联它们。

[你好] * 名称 = "!*将返回(假设名称设置为'John' 你好 约翰!.

()

调用可调用: { 发布.render() * 在括号内,您可以使用位置参数和关键字参数,如 Python 中:

{ post.render(用户,完整=true) }

. / []

获取对象的属性。 (请参阅Variables

If 表达式

也可以使用内联(如果表达式)。 在某些情况下,这些非常有用。 例如,如果定义了变量,则可以使用它从一个模板扩展,否则可以从默认布局模板扩展:

{% extends layout_template if layout_template is defined else 'master.html' %}

一般语法是< 做某事> 如果某物真, < 执行其他操作 > .

其他部分是可选的。 如果未提供,else 块隐式计算为Undefined对象(无论环境中undefined的内容设置为什么):

{{ "[{}]".format(page.title) if page.title }}

Python 方法|

还可以使用在变量类型上定义的任何方法。 从方法调用返回的值用作表达式的值。 下面是一个使用在字符串上定义的方法的示例(其中page.title是字符串):

{{ page.title.capitalize() }}

这适用于用户定义类型上的方法。 例如,如果Foo类型的变量f上定义了方法bar,则可以执行以下操作:

{{ f.bar(value) }}

运算符方法也按预期工作。 例如, %实现字符串的 printf 样式:

{{ "Hello, %s!" % name }}

虽然您应该选择这种情况的.format方法(这在呈现模板的上下文中是有点精心设计的):

{{ "Hello, {}!".format(name) }}

内置过滤器列表|

abs()

float()

lower()

round()

tojson()

attr()

forceescape()

map()

safe()

trim()

batch()

format()

max()

select()

truncate()

capitalize()

groupby()

min()

selectattr()

unique()

center()

indent()

pprint()

slice()

upper()

default()

int()

random()

sort()

urlencode()

dictsort()

join()

reject()

string()

urlize()

escape()

last()

rejectattr()

striptags()

wordcount()

filesizeformat()

length()

replace()

sum()

wordwrap()

first()

list()

reverse()

title()

xmlattr()

abs(x, /)

返回参数的绝对值。

attr(obj, name)

获取对象的属性。 foo|attr("bar")的工作方式与foo.bar类似,只是始终返回属性,并且不显示项目。

有关详细信息,请参阅Notes on subscriptions

batch(value, linecount, fill_with=None)

批处理项目的筛选器。 它的工作原理很像切片,只是相反。 它返回具有给定项数的列表列表。 如果提供第二个参数,则用于填充缺少的项。 请参阅此示例:

<table>
{%- for row in items|batch(3, '&nbsp;') %}
  <tr>
  {%- for column in row %}
    <td>{{ column }}</td>
  {%- endfor %}
  </tr>
{%- endfor %}
</table>
capitalize(s)

大写值。 第一个字符将是大写,所有其他小写。

center(value, width=80)

将值居中为给定宽度的字段。

default(value, default_value='', boolean=False)

如果该值未定义,它将返回传递的默认值,否则变量的值:

{{ my_variable|default('my_variable is not defined') }}

如果定义了变量,这将输出my_variable的值,否则"定义my_variable"。 如果要将默认值与计算为 false 的变量一起使用,必须将第二个参数设置为true

{{ ''|default('the string was empty', true) }}

在版本 2.11 中更改: 现在,可以使用ChainableUndefined"配置Environment,以使默认筛选器适用于在链中可能包含未定义值的嵌套元素和属性,而无需获取UndefinedError

别名

d

dictsort(value, case_sensitive=False, by='key', reverse=False)

对听写和屈服(键,值)对进行排序。 由于 python 分号未排序,您可能需要使用此函数按键或值对它们进行排序:

{% for item in mydict|dictsort %}
    sort the dict by key, case insensitive

{% for item in mydict|dictsort(reverse=true) %}
    sort the dict by key, case insensitive, reverse order

{% for item in mydict|dictsort(true) %}
    sort the dict by key, case sensitive

{% for item in mydict|dictsort(false, 'value') %}
    sort the dict by value, case insensitive
escape(s)

将字符串中的字符 *、*、*、"和"转换为 HTML 安全序列。 如果需要在 HTML 中显示可能包含此类字符的文本,请使用此选项。 将返回值标记为标记字符串。

别名

e

filesizeformat(value, binary=False)

将值格式化为"人可读"文件大小(即 13 kB、4.1 MB、102 字节等)。 如果使用每个默认十进制前缀(兆丰、千兆等),则第二个参数设置为True,则使用二进制前缀(Mebi、Gibi)。

first(seq)

返回序列的第一个项。

float(value, default=0.0)

将值转换为浮点数。 如果转换不起作用,它将返回0.0 您可以使用第一个参数重写此默认值。

forceescape(value)

强制 HTML 转义。 这可能加倍转义变量。

format(value, *args, **kwargs)

将给定值应用于printf 样式的格式字符串,如字符串 %

{{ "%s, %s!"|format(greeting, name) }}
Hello, World!

在大多数情况下,使用%运算符或str.format()应该更方便、更高效。

{{ "%s, %s!" % (greeting, name) }}
{{ "{}, {}!".format(greeting, name) }}
groupby(value, attribute)

使用 Python 的itertools.groupby()按属性按属性对对象序列进行分组。 该属性可以使用点表示法进行嵌套访问,如"address.city" 与 Python 的groupby不同,这些值首先排序,因此每个唯一值只返回一个组。

例如,具有city属性的User对象列表可以分组呈现。 在此示例中,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产生名为tuples 的(组目,列表),可以使用,而不是上面的元组解压。 grouper是属性的值,list是具有该值的项。

<ul>{% for group in users|groupby("city") %}
  <li>{{ group.grouper }}: {{ group.list|join(", ") }}
{% endfor %}</ul>
更改日志

在版本 2.6 中更改: 该属性支持嵌套访问的点表示法。

indent(s, width=4, first=False, blank=False, indentfirst=None)

返回字符串的副本,每行缩进 4 个空格。 默认情况下,第一行和空行不会缩进。

参数
  • 宽度= 要缩进的空间数。

  • 第一= 不要跳过缩进第一行。

  • 空白= 不要跳过缩进空行。

更改日志

在版本 2.10 中更改: 默认情况下,空白行不会缩进。

indentfirst参数重命名为first个 。

int(value, default=0, base=10)

将值转换为整数。 如果转换不起作用,它将返回0 您可以使用第一个参数重写此默认值。 您还可以重写第二个参数中的默认基 (10),该参数分别处理具有库 2、8 和 16 的前缀(如 0b、0o 和 0x)的输入。 对于十进制数字和非字符串值,将忽略基。

join(value, d='', attribute=None)

返回序列中字符串的串联字符串。 元素之间的分隔符是每个默认值的空字符串,您可以使用可选参数定义它:

{{ [1, 2, 3]|join('|') }}
    -> 1|2|3

{{ [1, 2, 3]|join }}
    -> 123

还可以联接对象的某些属性:

{{ users|join(', ', attribute='username') }}
更改日志

版本 2.6 中的新增功能: 已添加属性参数。

last(seq)

返回序列的最后一项。

注意:不适用于发电机。 您可能希望显式将其转换为列表:

{{ data | selectattr('name', '==', 'Jinja') | list | last }}
length(obj, /)

返回容器中的项数。

别名

计数

list(value)

将值转换为列表。 如果是字符串,则返回的列表将是字符列表。

lower(s)

将值转换为小写。

map(*args, **kwargs)

对对象序列应用筛选器或查找属性。 在处理对象列表时,这非常有用,但您实际上只对对象的特定值感兴趣。

基本用法是映射属性。 假设您有一个用户列表,但您只对用户名列表感兴趣:

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)
(u.username or "Anonymous" for u in users)
(do_lower(x) for x in titles)

在版本 2.11.0 中更改: 添加了default参数。

更改日志

版本 2.7 中新增。

max(value, case_sensitive=False, attribute=None)

从序列中返回最大的项。

{{ [1, 2, 3]|max }}
    -> 3
参数
  • case_sensitive = 将大写字符串和小写字符串视为不同的字符串。

  • 属性= 获取具有此属性的最大值的对象。

min(value, case_sensitive=False, attribute=None)

从序列中返回最小项。

{{ [1, 2, 3]|min }}
    -> 1
参数
  • case_sensitive = 将大写字符串和小写字符串视为不同的字符串。

  • 属性= 获取具有此属性的最小值的对象。

pprint(value, verbose=False)

漂亮的打印变量。 可用于调试。

使用 Jinja 1.2,您可以传递一个参数。 如果这个参数是真理输出将更详细(这需要漂亮的

random(seq)

从序列返回随机项。

reject(*args, **kwargs)

通过将测试应用于每个对象,并拒绝测试成功的对象来筛选对象序列。

如果未指定测试,则每个对象都将计算为布尔值。

示例用法:

{{ numbers|reject("odd") }}

类似于生成器理解,例如:

(n for n in numbers if not test_odd(n))
更改日志

版本 2.7 中新增。

rejectattr(*args, **kwargs)

通过将测试应用于每个对象的指定属性,并拒绝测试成功的对象来筛选对象序列。

如果未指定任何测试,则属性的值将计算为布尔值。

{{ 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))
更改日志

版本 2.7 中新增。

replace(s, old, new, count=None)

返回一个值的副本,该值的所有匹配项都替换为新子字符串。 第一个参数是应替换的子字符串,第二个参数是替换字符串。 如果给出可选的第三个参数count,则仅替换第一个count匹配项:

{{ "Hello World"|replace("Hello", "Goodbye") }}
    -> Goodbye World

{{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
    -> d'oh, d'oh, aaargh
reverse(value)

反转对象或返回迭代的对象。相反。

round(value, precision=0, method='common')

将数字舍入为给定精度。 第一个参数指定精度(默认值为0第二个参数指定舍入方法:

  • 'common'向上或向下轮

  • 'ceil'总是四舍五入

  • 'floor'总是向下舍入

如果不指定"'common'方法。

{{ 42.55|round }}
    -> 43.0
{{ 42.55|round(1, 'floor') }}
    -> 42.5

请注意,即使四舍五入为 0 精度,也会返回浮点。 如果您需要一个真正的整数,通过int管道它:

{{ 42.55|round|int }}
    -> 43
safe(value)

将该值标记为安全,这意味着在启用了自动转义的环境中,此变量将不会被转义。

select(*args, **kwargs)

通过将测试应用于每个对象,并仅选择测试成功的对象来筛选对象序列。

如果未指定测试,则每个对象都将计算为布尔值。

示例用法:

{{ 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))
更改日志

版本 2.7 中新增。

selectattr(*args, **kwargs)

通过将测试应用于每个对象的指定属性来筛选对象序列,并且仅选择测试成功的对象。

如果未指定任何测试,则属性的值将计算为布尔值。

示例用法:

{{ 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))
更改日志

版本 2.7 中新增。

slice(value, slices, fill_with=None)

切片迭代器并返回包含这些项目的列表列表。 如果要创建包含三个表示列的 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, reverse=False, case_sensitive=False, attribute=None)

使用 Python 的sorted()对可迭代进行排序。

{% for city in cities|sort %}
    ...
{% endfor %}
参数
  • 反向= 对降序排序,而不是升序。

  • case_sensitive – 对字符串进行排序时,分别对大写和小写进行排序。

  • 属性– 对对象或听写进行排序时,要排序的属性或键。 可以使用点表示法,如"address.city" 可以是"age,name"等属性的列表。

排序是稳定的,它不会改变比较相等的元素的相对顺序。 这样就可以对不同的属性和排序进行链排序。

{% for user in users|sort(attribute="name")
    |sort(reverse=true, attribute="age") %}
    ...
{% endfor %}

当所有属性的方向相同时,作为链接的快捷方式,传递一个逗号单独的属性列表。

{% for user users|sort(attribute="age,name") %}
    ...
{% endfor %}

在版本 2.11.0 中更改: attribute参数可以是逗号分隔的属性列表,例如"age,name"

更改日志

在版本 2.6 中更改: 已添加attribute参数。

string(object)

如果字符串尚未编码,则制作单编码。 这样,标记字符串就不会转换回单码。

striptags(value)

剥离 SGML/XML 标记,并将相邻的空白替换为一个空格。

sum(iterable, attribute=None, start=0)

返回数字序列的总和加上参数"start"的值(默认值为 0)。 当序列为空时,它将返回开始。

也可以只总结某些属性:

Total: {{ items|sum(attribute='price') }}
更改日志

在版本 2.6 中更改: 添加了属性参数以允许对属性进行汇总。 此外,开始参数也移到了右侧。

title(s)

返回值的标题大小。 即单词将以大写字母开头,所有剩余字符都是小写。

tojson(value, indent=None)

将结构转储到 JSON,以便在<script>标记中安全使用。 它接受相同的参数并返回 JSON 字符串。 请注意,这在模板中可通过|tojson筛选器提供,该筛选器还会将结果标记为安全。 由于此函数如何转义某些字符,因此即使在<script>标记之外使用,也是安全的。

以下字符在字符串中转义:

  • <

  • >

  • &

  • '

这样,在 HTML 中的任何位置嵌入此类字符串都是安全的,但双引号属性的显著例外除外。 在这种情况下,单引号您的属性或 HTML 转义它之外。

缩进参数可用于启用漂亮的打印。 将其设置为结构应缩进的空间数。

请注意,此筛选器仅用于 HTML 上下文。

更改日志

版本 2.9 中的新增功能。

trim(value, chars=None)

按默认空白条条条条条和尾随字符。

truncate(s, length=255, killwords=False, end='...', leeway=None)

返回字符串的截断副本。 长度使用默认值为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, case_sensitive=False, attribute=None)

返回给定可迭代中的唯一项的列表。

{{ ['foo', 'bar', 'foobar', 'FooBar']|unique|list }}
    -> ['foo', 'bar', 'foobar']

唯一项的产生顺序与它们在传递给筛选器的可迭代项中的第一次出现的顺序相同。

参数
  • case_sensitive = 将大写字符串和小写字符串视为不同的字符串。

  • 属性= 筛选具有此属性的唯一值的对象。

upper(s)

将值转换为大写。

urlencode(value)

使用 UTF-8 在 URL 路径或查询中使用的报价数据。

给一个字符串或urllib.parse.urlencode()时围绕urllib.parse.quote()的基本包装器,用于听写或可迭代。

参数

= 要引用的数据。 字符串将直接引用。 口述或迭代将作为查询字符串联接。

给定字符串时,"/"不引用。 HTTP 服务器在路径中处理"/"和"%2F"。 如果需要带号斜杠,请使用_replace("/","%2F")过滤器。

更改日志

版本 2.7 中新增。

urlize(value, trim_url_limit=None, nofollow=False, target=None, rel=None)

将纯文本中的 URL 转换为可单击的链接。

如果传递筛选器另一个整数,它将缩短该数字的 URL。 还有第三个参数,使 url"不跟随":

{{ mytext|urlize(40, true) }}
    links are shortened to 40 chars and defined with rel="nofollow"

如果指定了目标target属性将添加到<a>标记中:

{{ mytext|urlize(40, target='_blank') }}
更改日志

在版本 2.8* 中更改: 已添加目标参数。

wordcount(s)

计算该字符串中的单词。

wordwrap(s, width=79, break_long_words=True, wrapstring=None, break_on_hyphens=True)

将字符串换行到给定宽度。 现有换行线被视为要单独换行的段落。

参数
  • s = 要换行的原始文本。

  • 宽度= 换行的最大长度。

  • break_long_words —— 如果单词长于width,则跨行将其断开。

  • break_on_hyphens – 如果单词包含连字符,则它可能跨行拆分。

  • 换行字符串= 字符串以联接每个换行的行。 默认为Environment.newline_sequence

在版本 2.11 中更改: 现有换行线被视为单独包装的段落。

在版本 2.11 中更改: 添加了break_on_hyphens参数。

更改日志

在版本 2.7 中更改: 添加了wrapstring参数。

xmlattr(d, autospace=True)

根据听写中的项创建 SGML/XML 属性字符串。 自动转义所有既不是未定义的值:

<ul{{ {'class': 'my_list', 'missing': none,
        'id': 'list-%d'|format(variable)}|xmlattr }}>
...
</ul>

结果如下所示:

<ul class="my_list" id="list-42">
...
</ul>

正如您所看到的,如果筛选器返回了某些内容,除非第二个参数为 false,则它会自动预置项目前面的空格。

内置测试列表|

boolean()

even()

integer()

ne()

string()

callable()

false()

iterable()

none()

true()

defined()

float()

le()

number()

undefined()

divisibleby()

ge()

lower()

odd()

upper()

eq()

gt()

lt()

sameas()

escaped()

in()

mapping()

sequence()

boolean(value)

如果对象是布尔值,则返回 true。

版本 2.11 中的新增功能。

callable(obj, /)

返回对象是否可调用(即某种函数)。

请注意,类是可调用的,使用 __call__() 方法的类的实例也是可调用的。

defined(value)

如果定义了变量,则返回 true:

{% if variable is defined %}
    value of variable: {{ variable }}
{% else %}
    variable is not defined
{% endif %}

有关设置未定义变量的简单方法,请参阅default()筛选器。

divisibleby(value, num)

检查变量是否被数字整除。

eq(a, b)
别名

==equalto

escaped(value)

检查值是否转义。

even(value)

如果变量为偶数,则返回 true。

false(value)

如果对象为 False,则返回 true。

版本 2.11 中的新增功能。

float(value)

如果对象是浮点子,则返回 true。

版本 2.11 中的新增功能。

ge(a, b)
别名

>=

gt(a, b)
别名

>greaterthan

in(value, seq)

检查值是否以 seq 表示。

更改日志

版本 2.10 中的新增功能。

integer(value)

如果对象是整数,则返回 true。

版本 2.11 中的新增功能。

iterable(value)

检查是否可以迭代对象。

le(a, b)
别名

<=

lower(value)

如果变量小写,则返回 true。

lt(a, b)
别名

<lessthan

mapping(value)

如果对象是映射(dict 等),则返回 true。

更改日志

版本 2.6 中的新增功能。

ne(a, b)
别名

!=

none(value)

如果变量为 none,则返回 true。

number(value)

如果变量是数字,则返回 true。

odd(value)

如果变量为奇数,则返回 true。

sameas(value, other)

检查对象是否指向与另一个对象相同的内存地址:

{% if foo.attribute is sameas false %}
    the foo attribute really is the `False` singleton
{% endif %}
sequence(value)

如果变量是序列,则返回 true。 序列是可迭代的变量。

string(value)

如果对象是字符串,则返回 true。

true(value)

如果对象为 True,则返回 true。

版本 2.11 中的新增功能。

undefined(value)

喜欢defined()但相反。

upper(value)

如果变量大写,则返回 true。

全局函数列表

默认情况下,全局作用域中提供以下函数:

range([start, ]stop[, step])

返回包含整数算术级数的列表。 范围(i,j)返回[i,i=1,i=2,...,j-1]; 开始(! 默认值为0 给定步长时,它指定增量(或递减)。 例如,range(4)范围(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。 默认情况下,每个段落在 20 到 100 个单词之间生成五个 HTML 段落。 如果 html 为 False,则返回常规文本。 这对于生成用于布局测试的简单内容非常有用。

dict(**items)

听写字的方便替代方案。 ['foo': "酒吧"* 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>
参数

= 每个位置参数将按每个周期给出的顺序产生。

更改日志

版本 2.1 中的新增功能。

property current

返回当前项目。 等效于next()将返回的项。

next()

返回当前物料,然后将current物料前进到下一个物料。

reset()

将当前项目重置为第一项。

class joiner(sep=', ')

一个微型帮助器,可用于"联接"多个部分。 joiner 传递一个字符串,并在每次调用该字符串时返回该字符串,但第一次除外(在这种情况下,它将返回一个空字符串)。 您可以使用它来联接内容:

{% 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 %}
更改日志

版本 2.1 中的新增功能。

class namespace(...)

创建一个允许使用[% %]标记进行属性分配的新容器:

{% set ns = namespace() %}
{% set ns.foo = 'bar' %}

这样做的主要目的是允许将值从循环体内携带到外部作用域。 初始值可以作为听写、关键字参数或两者提供(与 Python 的听写构造函数相同的行为):

{% 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 }}
更改日志

版本 2.10 中的新增功能。

扩展

以下各节介绍应用程序可能启用的内置 Jinja 扩展。 应用程序还可以提供本文档未涵盖的进一步扩展;在这种情况下,应该有一个单独的文件解释该extensions

i18n|

如果启用了i18n Extension,则可以将模板中的文本标记为可翻译。 要将节标记为可翻译,请使用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 book_title=book.title %}
    This is {{ book_title }}.
    You should read it!
{% endtrans %}

这将导致 %(book_title) 应该 它! 在翻译文件中。

如果全局启用修剪,则可用于禁用块的notrimmed修改器。

更改日志

版本 2.10 中的新增功能: 已添加trimmednotrimmed的修饰符。

可以使用以下函数翻译表达式中的字符串:

  • gettext: 翻译单个字符串

  • ngettext: 翻译一个复数字符串

  • _gettext的别名

您可以打印如下所示的翻译字符串:

{{ _("Hello, World!") }}

要使用占位符,请使用format筛选器。

{{ _("Hello, %(user)s!")|format(user=user.username) }}

始终使用关键字参数format,因为其他语言可能不会以相同的顺序使用单词。

如果激活了New Style 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') %}

循环控制|

如果应用程序启用Loop Controls,则可以使用中断并在循环中继续 当达到中断时,循环将终止;如果达到中断,则循环将终止。如果达到继续,则停止处理并继续下一次迭代。

下面是跳过每个第二项的循环:

{% 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 开头(请参阅: For)。

调试语句|

如果启用Debug Extension,则{% 调试 %_ 标记将可用于转储当前上下文以及可用的筛选器和测试。 这对于在不设置调试器的情况下查看模板中可以使用的内容非常有用。

<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']}

With 语句

更改日志

版本 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 版本中,将一个变量引用到另一个变量的行为产生了一些意想不到的后果。 特别是,一个变量可以引用同一块的开头语句中定义的另一个变量。 这造成了清理范围行为的问题,并且自此得到了改进。 特别是在较新的 Jinja 版本中,以下代码始终引用来自from块外部的变量a:

{% with a={}, b=a.attribute %}...{% endwith %}

在早期的 Jinja 版本中,b属性将引用第一个属性的结果。 如果依赖于此行为,则可以重写它以使用set标记:

{% with a={} %}
    {% set b = a.attribute %}
{% endwith %}

扩展

在旧版本的 Jinja(2.9 之前),需要使用扩展启用此功能。 现在默认启用。

自动转义覆盖|

更改日志

版本 2.4 中的新增功能。

如果需要,可以从模板中激活和停用自动转义。

例子:

{% autoescape true %}
    Autoescaping is active within this block
{% endautoescape %}

{% autoescape false %}
    Autoescaping is inactive within this block
{% endautoescape %}

结束自动转义后,行为将恢复为以前。

扩展

在旧版本的 Jinja(2.9 之前),需要使用扩展启用此功能。 现在默认启用。