模板設計器文檔?

本文檔描述了模板引擎的語法和語義,對于創建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分隔符配置如下:

模板文件擴展名?

如上所述,任何文件都可以作為模板加載,而不考慮文件擴展名。添加 .jinja 延伸,比如 user.html.jinja 可能會使一些ide或編輯器插件更容易,但不是必需的。后面介紹的自動轉義可以基于文件擴展名應用,因此在這種情況下,需要考慮額外的后綴。

另一個識別模板的好方法是它們在 templates 文件夾,不考慮擴展名。這是項目的常見布局。

變量?

模板變量由傳遞給模板的上下文字典定義。

如果應用程序傳入了模板中的變量,那么您可以隨意處理這些變量。變量上可能有屬性或元素,您也可以訪問它們。變量的屬性在很大程度上取決于提供該變量的應用程序。

你可以用圓點 (. )訪問除標準python之外的變量屬性 __getitem__ “下標”語法 ([]

以下幾行的作用相同:

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

重要的是要知道外部的雙花括號是 not 變量的一部分,但打印語句。如果訪問標記內的變量,不要在它們周圍加括號。

如果變量或屬性不存在,您將返回未定義的值。使用這種類型的值可以做什么取決于應用程序配置:默認行為是在打印或迭代時計算為空字符串,并在其他每個操作中失敗。

實施

為了方便起見, foo.bar 在Jinja中,在Python層上執行以下操作:

  • 檢查調用的屬性 barfoo (getattr(foo, 'bar')

  • 如果沒有,檢查項目 'bar' 在里面 foo (foo.__getitem__('bar')

  • 如果沒有,則返回未定義的對象。

foo['bar'] 工作原理基本相同,但順序差異較?。?/p>

  • 檢查項目 'bar' 在里面 foo . (foo.__getitem__('bar')

  • 如果沒有,請檢查調用的屬性 barfoo . (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_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>

類似地,您可以手動禁用 trim_blocks 加加號的行為 (+ )在一個街區的末尾:

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

您還可以手動去除模板中的空白。如果你加一個減號 (- )到塊的開始或結束(例如 為了 標記)、注釋或變量表達式,將刪除該塊之前或之后的空白:

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

這將生成所有元素,它們之間沒有空白。如果 seq 是來自 19 ,輸出為 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框架文檔,您可以將其用于簡單的兩列頁面?!白印蹦0宓娜蝿帐怯脙热萏畛淇諌K:

<!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 %}} 標記定義了子模板可以填充的四個塊。所有的 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的字符的風險。有兩種方法:

  1. 手動轉義每個變量;或

  2. 默認情況下自動轉義所有內容。

Jinja支持兩者。使用什么取決于應用程序配置。默認配置不是自動轉義;由于各種原因:

  • 轉義除安全值之外的所有內容還意味著Jinja轉義的變量不包括HTML(例如數字、布爾值),這可能會對性能造成巨大影響。

  • 有關變量安全性的信息非常脆弱。通過強制安全和不安全的值,返回值可能是雙轉義的HTML。

使用手動逃逸?

如果啟用了手動轉義,則 your 如有必要,負責逃逸變量。怎么逃跑?如果你有一個變量 may 包括以下任何字符 (> , < , &"SHOULD 除非變量包含格式良好且受信任的HTML,否則對其進行轉義。通過管道將變量通過 |e 過濾器:

{{ user.username|e }}

使用自動轉義?

啟用自動轉義后,默認情況下,除了顯式標記為安全的值外,所有內容都轉義。變量和表達式可以在以下位置標記為安全:

  1. 應用程序的上下文字典 markupsafe.Markup

  2. 模板,帶有 |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不同,它不可能 breakcontinue 在一個循環中但是,您可以在迭代期間過濾序列,這允許您跳過項目。以下示例跳過所有隱藏的用戶:

{% 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,在某些情況下,任務似乎可以工作。不支持此操作??吹搅藛?作業 有關如何處理此問題的詳細信息。

如果您只想檢查某個值自上次迭代以來是否發生了更改,或者在下一次迭代中將發生更改,則可以使用 previtemnextitem ::

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

對于多個分支, elifelse 可以像在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 %}

延伸?

這個 extends 標記可用于從一個模板擴展到另一個模板。你可以有多個 extends 文件中的標記,但一次只能執行其中一個標記。

參見關于 模板繼承 上面。

阻礙?

塊用于繼承,同時充當占位符和替換。它們詳細記錄在 模板繼承 部分。

包括?

這個 include 標記用于包含模板并將該文件的呈現內容返回到當前命名空間::

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

默認情況下,包含的模板可以訪問活動上下文的變量。有關導入和包含的上下文行為的詳細信息,請參閱 導入上下文行為 .

從Jinja 2.2起,您可以標記包含 ignore missing ;在這種情況下,如果要包含的模板不存在,Jinja將忽略該語句。當與 withwithout 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 contextwithout 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.htmlnot 能夠訪問 box 在Jinja2。從Jinja 2.1開始, render_box.html is 能夠做到這一點。

表達?

Jinja允許在任何地方使用基本的表達方式。這些方法與普通的python非常相似;即使您不使用python,也應該對它感到舒適。

直接常量?

最簡單的表達式形式是文本。文本是Python對象(如字符串和數字)的表示形式。存在以下文字:

"Hello World"

兩個雙引號或單引號之間的所有內容都是字符串。當您需要模板中的字符串時(例如,作為函數調用和篩選器的參數,或者只是為了擴展或包含模板),它們都非常有用。

42 / 123_456

整數是不帶小數部分的整數?!白址笨捎糜诜指艚M以確保易讀性。

42.23 / 42.1e2 / 123_456.789

浮點數可以用“.”作為小數點。它們也可以用科學記數法寫成,用大寫或小寫字母“e”表示指數部分?!白址笨捎糜诜指艚M以確保易讀性,但不能用于指數部分。

['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是一種組合鍵和值的結構。鍵必須唯一,并且始終只有一個值??谑鲈谀0逯泻苌偈褂?;它們在一些罕見的情況下很有用,例如 xmlattr() 過濾器。

true / false

true 總是正確的而且 false 總是假的。

注意

特殊常數 true , falsenone 確實是小寫的。因為這在過去引起了混亂, (True 用于擴展到被認為是錯誤的未定義變量),現在這三個變量都可以用標題大小寫 (True , FalseNone )但是,為了一致性,(所有的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)

括號將表達式分組。

注意

這個 isin 運算符也支持使用中綴表示法求反: foo is not barfoo not in bar 而不是 not foo is barnot 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()

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: 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, '&nbsp;') %}
  <tr>
  {%- for column in row %}
    <td>{{ column }}</td>
  {%- endfor %}
  </tr>
{%- endfor %}
</table>
capitalize(s: str) str?

將值大寫。第一個字符將為大寫,其他所有字符均為小寫。

center(value: str, width: int = 80) str?

將給定寬度的字段中的值居中。

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?

將值格式化為“人類可讀”的文件大?。?3 KB、4.1 MB、102字節等)。如果第二個參數設置為,則使用默認的十進制前綴(mega、giga等)。 True 使用二進制前綴(mebi、gibi)。

first(seq: 't.Iterable[V]') 't.Union[V, Undefined]'?

返回序列的第一項。

float(value: Any, default: float = 0.0) float?

將該值轉換為浮點數。如果轉換不起作用,它將返回 0.0 . 可以使用第一個參數覆蓋此默認值。

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: Union[Any, NoneType] = None) 't.List[t.Tuple[t.Any, t.List[V]]]'?

使用Python的 itertools.groupby() . 屬性可以對嵌套訪問使用點表示法,例如 "address.city" . 不像Python的 groupby ,首先對值進行排序,因此每個唯一值只返回一個組。

例如,列表 User 對象與A city 屬性可以分組呈現。在這個例子中, 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>

在 3.0 版更改: 增加了 default 參數。

Changelog

在 2.6 版更改: 該屬性支持嵌套訪問的點表示法。

indent(s: str, width: Union[int, str] = 4, first: bool = False, blank: bool = False) str?

返回字符串的副本,每行縮進4個空格。默認情況下,首行和空行不縮進。

參數
  • width -- 要縮進的空格或字符串的數量。

  • first -- 不要跳過首行縮進。

  • blank -- 不要跳過空行縮進。

在 3.0 版更改: width 可以是字符串。

Changelog

在 2.10 版更改: 默認情況下,空行不縮進。

重命名 indentfirst 參數 first .

int(value: Any, default: int = 0, base: int = 10) int?

將該值轉換為整數。如果轉換不起作用,它將返回 0 . 可以使用第一個參數覆蓋此默認值。您還可以重寫第二個參數中的默認基數(10),該參數用前綴(如0b、0o和0x)分別處理基數2、8和16的輸入。十進制數和非字符串值的基數被忽略。

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

將值轉換為列表。如果是字符串,則返回的列表將是字符列表。

lower(s: str) str?

將值轉換為小寫。

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 -- 獲取具有此屬性最小值的對象。

pprint(value: Any) str?

漂亮的打印變量。用于調試。

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: Union[int, NoneType] = 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
safe(value: str) markupsafe.Markup?

將該值標記為安全,這意味著在啟用自動轉義的環境中,不會轉義該變量。

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 -- 當對對象或指令進行排序時,要按其排序的屬性或鍵??梢杂命c表示法 "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 %}
Changelog

在 2.11.0 版更改: 這個 attribute 參數可以是逗號分隔的屬性列表,例如。 "age,name" .

在 2.6 版更改: 這個 attribute 已添加參數。

string(value)?

如果對象尚未轉換為字符串,請將其轉換為字符串。這將保留一個 Markup 字符串,而不是將其轉換回基本字符串,因此它仍將被標記為安全,并且不會再次轉義。

>>> value = escape("<User 1>")
>>> value
Markup('&lt;User 1&gt;')
>>> escape(str(value))
Markup('&amp;lt;User 1&amp;gt;')
>>> escape(soft_str(value))
Markup('&lt;User 1&gt;')
striptags(value: 't.Union[str, HasHTML]') str?

去掉sgml/xml標記并用一個空格替換相鄰的空白。

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 參數已移到右側。

title(s: str) str?

返回值的基于標題的版本。也就是說,單詞將以大寫字母開頭,其余所有字符都是小寫。

tojson(value: Any, indent: Union[int, NoneType] = None) markupsafe.Markup?

將對象序列化為JSON字符串,并將其標記為可以在HTML中安全呈現。此過濾僅用于Html文檔。

返回的字符串在HTML文檔中呈現是安全的,并且 <script> 標簽。例外是在用雙引號引起來的HTML屬性中;可以使用單引號,也可以使用 |forceescape 過濾。

參數
  • value -- 要序列化為JSON的對象。

  • indent -- 這個 indent 傳遞給的參數 dumps ,用于漂亮地打印價值。

Changelog

2.9 新版功能.

trim(value: str, chars: Union[str, NoneType] = None) str?

去掉前導字符和尾隨字符,默認為空白。

truncate(s: str, length: int = 255, killwords: bool = False, end: str = '...', leeway: Union[int, NoneType] = 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 -- 為此屬性篩選具有唯一值的對象。

upper(s: str) str?

將值轉換為大寫。

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: Union[int, NoneType] = None, nofollow: bool = False, target: Union[str, NoneType] = None, rel: Union[str, NoneType] = None, extra_schemes: Union[Iterable[str], NoneType] = 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"] ,它默認為沒有額外的方案。

在 3.0 版更改: 這個 extra_schemes 參數已添加。

在 3.0 版更改: 生成 https:// 沒有方案的URL鏈接。

在 3.0 版更改: 解析規則已更新。識別電子郵件地址,無論是否使用 mailto: 計劃。驗證IP地址。在更多情況下忽略圓括號和方括號。

Changelog

在 2.8 版更改: 這個 target 參數已添加。

wordcount(s: str) int?

數一數那個字符串中的單詞。

wordwrap(s: str, width: int = 79, break_long_words: bool = True, wrapstring: Union[str, NoneType] = None, break_on_hyphens: bool = True) str?

將字符串按給定寬度換行?,F有換行符被視為要單獨包裝的段落。

參數
  • 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,否則它會自動在項目前面預留一個空格。

內置測試列表?

boolean()

even()

in()

mapping()

sequence()

callable()

false()

integer()

ne()

string()

defined()

filter()

iterable()

none()

test()

divisibleby()

float()

le()

number()

true()

eq()

ge()

lower()

odd()

undefined()

escaped()

gt()

lt()

sameas()

upper()

boolean(value: Any) bool?

如果對象是布爾值,則返回true。

Changelog

2.11 新版功能.

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() 篩選以獲取設置未定義變量的簡單方法。

divisibleby(value: int, num: int) bool?

檢查變量是否可被數字整除。

eq(a, b, /)?

與a==b相同。

別名

==, equalto

escaped(value: Any) bool?

檢查值是否已轉義。

even(value: int) bool?

如果變量為偶數,則返回true。

false(value: Any) bool?

如果對象為False,則返回true。

Changelog

2.11 新版功能.

filter(value: str) bool?

按名稱檢查是否存在過濾。如果可能有過濾可選,則非常有用。

{% if 'markdown' is filter %}
    {{ value | markdown }}
{% else %}
    {{ value }}
{% endif %}

3.0 新版功能.

float(value: Any) bool?

如果對象是float,則返回true。

Changelog

2.11 新版功能.

ge(a, b, /)?

與a>=b相同。

別名

>=

gt(a, b, /)?

與a>b相同。

別名

>, greaterthan

in(value: Any, seq: Container) bool?

檢查值是否在seq中。

Changelog

2.10 新版功能.

integer(value: Any) bool?

如果對象是整數,則返回true。

Changelog

2.11 新版功能.

iterable(value: Any) bool?

檢查是否可以迭代對象。

le(a, b, /)?

與a<=b相同。

別名

<=

lower(value: str) bool?

如果變量的基數較低,則返回true。

lt(a, b, /)?

與a<b相同。

別名

<, lessthan

mapping(value: Any) bool?

如果對象是映射(dict等),則返回true。

Changelog

2.6 新版功能.

ne(a, b, /)?

和a一樣!=b。

別名

!=

none(value: Any) bool?

如果變量為“無”,則返回“真”。

number(value: Any) bool?

如果變量是數字,則返回true。

odd(value: int) bool?

如果變量是奇數,則返回true。

sameas(value: Any, other: Any) bool?

檢查一個對象是否指向與另一個對象相同的內存地址:

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

如果變量是序列,則返回true。序列是不可迭代的變量。

string(value: Any) bool?

如果對象是字符串,則返回true。

test(value: str) bool?

按名稱檢查是否存在測試。如果測試可能是可選的,則非常有用。

{% if 'loud' is test %}
    {% if value is loud %}
        {{ value|upper }}
    {% else %}
        {{ value|lower }}
    {% endif %}
{% else %}
    {{ value }}
{% endif %}

3.0 新版功能.

true(value: Any) bool?

如果對象為true,則返回true。

Changelog

2.11 新版功能.

undefined(value: Any) bool?

喜歡 defined() 但反過來說。

upper(value: str) bool?

如果變量為大寫,則返回true。

全局函數列表?

默認情況下,以下函數在全局范圍內可用:

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

返回包含整數算術級數的列表。 range(i, j) 收益率 [i, i+1, i+2, ..., j-1] 開始(?。┠J為 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 新版功能.

property current?

返回當前項。相當于下次將返回的項 next() 被稱為。

next()?

返回當前項目,然后前進 current 到下一個項目。

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 新版功能: 這個 trimmednotrimmed 已添加修飾符。

可以使用以下函數轉換表達式中的字符串:

  • gettext :轉換單個字符串

  • ngettext :轉換可復數字符串

  • _: alias for gettext

您可以像這樣打印字符串:

{{ _("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') %}

循環控制?

如果應用程序啟用 循環控制 ,可以使用 breakcontinue 在循環中。什么時候? 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之前)中,需要通過擴展來啟用此功能。它現在默認啟用。