這份文檔描述了模板引擎中的語法和語義結(jié)構(gòu),對(duì)于創(chuàng)建 Jinja 模板是一份相當(dāng)有用 的參考。因?yàn)槟0逡娣浅l`活,應(yīng)用中的配置會(huì)在分隔符和未定義值的行為方面與 這里的配置有細(xì)微差異。
模板僅僅是文本文件。它可以生成任何基于文本的格式(HTML、XML、CSV、LaTex 等等)。 它并沒有特定的擴(kuò)展名, .html 或 .xml 都是可以的。
模板包含 變量 或 表達(dá)式 ,這兩者在模板求值的時(shí)候會(huì)被替換為值。模板中 還有標(biāo)簽,控制模板的邏輯。模板語法的大量靈感來自于 Django 和 Python 。
下面是一個(gè)最小的模板,它闡明了一些基礎(chǔ)。我們會(huì)在文檔中后面的部分解釋細(xì)節(jié):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<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 }}
</body>
</html>
這包含了默認(rèn)的設(shè)定。應(yīng)用開發(fā)者也會(huì)把語法從 {% foo %} 改成 <% foo %> 或類似的東西。
這里有兩種分隔符: {% ... %} 和 {{ ... }} 。前者用于執(zhí)行諸如 for 循環(huán) 或賦值的語句,后者把表達(dá)式的結(jié)果打印到模板上。
應(yīng)用把變量傳遞到模板,你可能在模板中弄混。變量上面也可以有你能訪問的屬性或元 素。變量看起來是什么,完全取決于應(yīng)用提供了什么。
你可以使用點(diǎn)( . )來訪問變量的屬性,作為替代,也可以使用所謂的"下標(biāo)"語 法( [] )。下面的幾行效果是一樣的:
{{ foo.bar }}
{{ foo['bar'] }}
知曉花括號(hào) 不是 變量的一部分,而是打印語句的一部分是重要的。如果你訪問標(biāo)簽 里的不帶括號(hào)的變量。
如果變量或?qū)傩圆淮嬖?,?huì)返回一個(gè)未定義值。你可以對(duì)這類值做什么取決于應(yīng)用的配 置,默認(rèn)的行為是它如果被打印,其求值為一個(gè)空字符串,并且你可以迭代它,但其它 操作會(huì)失敗。
實(shí)現(xiàn)
為方便起見,Jinja2 中
foo.bar在 Python 層中做下面的事情:
- 檢查 foo 上是否有一個(gè)名為 bar 的屬性。
- 如果沒有,檢查 foo 中是否有一個(gè)
'bar'項(xiàng) 。- 如果沒有,返回一個(gè)未定義對(duì)象。
foo['bar']的方式相反,只在順序上有細(xì)小差異:
- 檢查在 foo 中是否有一個(gè)
'bar'項(xiàng)。- 如果沒有,檢查 foo 上是否有一個(gè)名為 bar 的屬性。
- 如果沒有,返回一個(gè)未定義對(duì)象。
如果一個(gè)對(duì)象有同名的項(xiàng)和屬性,這很重要。此外,有一個(gè)
attr()過濾 器,它只查找屬性。
變量可以通過 過濾器 修改。過濾器與變量用管道符號(hào)( | )分割,并且也 可以用圓括號(hào)傳遞可選參數(shù)。多個(gè)過濾器可以鏈?zhǔn)秸{(diào)用,前一個(gè)過濾器的輸出會(huì)被作為 后一個(gè)過濾器的輸入。
例如 {{ name|striptags|title }} 會(huì)移除 name 中的所有 HTML 標(biāo)簽并且改寫 為標(biāo)題樣式的大小寫格式。過濾器接受帶圓括號(hào)的參數(shù),如同函數(shù)調(diào)用。這個(gè)例子會(huì) 把一個(gè)列表用逗號(hào)連接起來: {{ list|join(', ') }} 。
下面的 內(nèi)置過濾器清單 節(jié)介紹了所有的內(nèi)置過濾器。
除了過濾器,所謂的"測(cè)試"也是可用的。測(cè)試可以用于對(duì)照普通表達(dá)式測(cè)試一個(gè)變量。 要測(cè)試一個(gè)變量或表達(dá)式,你要在變量后加上一個(gè) is 以及測(cè)試的名稱。例如,要得出 一個(gè)值是否定義過,你可以用 name is defined ,這會(huì)根據(jù) name 是否定義返回 true 或 false 。
測(cè)試也可以接受參數(shù)。如果測(cè)試只接受一個(gè)參數(shù),你可以省去括號(hào)來分組它們。例如, 下面的兩個(gè)表達(dá)式做同樣的事情:
{% if loop.index is divisibleby 3 %}
{% if loop.index is divisibleby(3) %}
下面的 內(nèi)置測(cè)試清單 章節(jié)介紹了所有的內(nèi)置測(cè)試。
要把模板中一行的部分注釋掉,默認(rèn)使用 {# ... #} 注釋語法。這在調(diào)試或 添加給你自己或其它模板設(shè)計(jì)者的信息時(shí)是有用的:
{# note: disabled template because we no longer use this
{% for user in users %}
...
{% endfor %}
#}
默認(rèn)配置中,模板引擎不會(huì)對(duì)空白做進(jìn)一步修改,所以每個(gè)空白(空格、制表符、換行符 等等)都會(huì)原封不動(dòng)返回。如果應(yīng)用配置了 Jinja 的 trim_blocks ,模板標(biāo)簽后的 第一個(gè)換行符會(huì)被自動(dòng)移除(像 PHP 中一樣)。
此外,你也可以手動(dòng)剝離模板中的空白。當(dāng)你在塊(比如一個(gè) for 標(biāo)簽、一段注釋或變 量表達(dá)式)的開始或結(jié)束放置一個(gè)減號(hào)( - ),可以移除塊前或塊后的空白:
{% for item in seq -%}
{{ item }}
{%- endfor %}
這會(huì)產(chǎn)出中間不帶空白的所有元素。如果 seq 是 1 到 9 的數(shù)字的列表, 輸出會(huì)是 123456789 。
如果開啟了 行語句 ,它們會(huì)自動(dòng)去除行首的空白。
提示
標(biāo)簽和減號(hào)之間不能有空白。
有效的:
{%- if foo -%}...{% endif %}無效的:
{% - if foo - %}...{% endif %}
有時(shí)想要或甚至必要讓 Jinja 忽略部分,不會(huì)把它作為變量或塊來處理。例如,如果 使用默認(rèn)語法,你想在在使用把 {{ 作為原始字符串使用,并且不會(huì)開始一個(gè)變量 的語法結(jié)構(gòu),你需要使用一個(gè)技巧。
最簡(jiǎn)單的方法是在變量分隔符中( {{ )使用變量表達(dá)式輸出:
{{ '{{' }}
對(duì)于較大的段落,標(biāo)記一個(gè)塊為 raw 是有意義的。例如展示 Jinja 語法的實(shí)例, 你可以在模板中用這個(gè)片段:
{% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
如果應(yīng)用啟用了行語句,就可以把一個(gè)行標(biāo)記為一個(gè)語句。例如如果行語句前綴配置為 # ,下面的兩個(gè)例子是等價(jià)的:
<ul>
# for item in seq
<li>{{ item }}</li>
# endfor
</ul>
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
行語句前綴可以出現(xiàn)在一行的任意位置,只要它前面沒有文本。為了語句有更好的可讀 性,在塊的開始(比如 for 、 if 、 elif 等等)以冒號(hào)結(jié)尾:
# for item in seq:
...
# endfor
提示
若有未閉合的圓括號(hào)、花括號(hào)或方括號(hào),行語句可以跨越多行:
<ul> # for href, caption in [('index.html', 'Index'), ('about.html', 'About')]: <li><a href="{{ href }}">{{ caption }}</a></li> # endfor </ul>
從 Jinja 2.2 開始,行注釋也可以使用了。例如如果配置 ## 為行注釋前綴, 行中所有 ## 之后的內(nèi)容(不包括換行符)會(huì)被忽略:
# for item in seq:
<li>{{ item }}</li> ## this comment is ignored
# endfor
Jinja 中最強(qiáng)大的部分就是模板繼承。模板繼承允許你構(gòu)建一個(gè)包含你站點(diǎn)共同元素的基 本模板"骨架",并定義子模板可以覆蓋的 塊 。
聽起來復(fù)雜,實(shí)際上很簡(jiǎn)單。從例子上手是最易于理解的。
這個(gè)模板,我們會(huì)把它叫做 base.html ,定義了一個(gè)簡(jiǎn)單的 HTML 骨架文檔,你可 能使用一個(gè)簡(jiǎn)單的兩欄頁面。用內(nèi)容填充空的塊是子模板的工作:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<html xmlns="http://www.w3.org/1999/xhtml">
<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 >you</a>.
{% endblock %}
</div>
</body>
在本例中, {% block %} 標(biāo)簽定義了四個(gè)字幕版可以填充的塊。所有的 block 標(biāo)簽 告訴模板引擎子模板可以覆蓋模板中的這些部分。
一個(gè)子模板看起來是這樣:
{% 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 on my awesome homepage.
</p>
{% endblock %}
{% extend %} 標(biāo)簽是這里的關(guān)鍵。它告訴模板引擎這個(gè)模板"繼承"另一個(gè)模板。 當(dāng)模板系統(tǒng)對(duì)這個(gè)模板求值時(shí),首先定位父模板。 extends 標(biāo)簽應(yīng)該是模板中的第一個(gè) 標(biāo)簽。它前面的所有東西都會(huì)按照普通情況打印出來,而且可能會(huì)導(dǎo)致一些困惑。更多 該行為的細(xì)節(jié)以及如何利用它,見 Null-Master 退回 。
模板的文件名依賴于模板加載器。例如 FileSystemLoader 允許你用文件名訪 問其它模板。你可以使用斜線訪問子目錄中的模板:
{% extends "layout/default.html" %}
這種行為也可能依賴于應(yīng)用內(nèi)嵌的 Jinja 。注意子模板沒有定義 footer 塊,會(huì) 使用父模板中的值。
你不能在同一個(gè)模板中定義多個(gè)同名的 {% block %} 標(biāo)簽。因?yàn)閴K標(biāo)簽以兩種 方向工作,所以存在這種限制。即一個(gè)塊標(biāo)簽不僅提供一個(gè)可以填充的部分,也在父級(jí) 定義填充的內(nèi)容。如果同一個(gè)模板中有兩個(gè)同名的 {% blok %} 標(biāo)簽,父模板 無法獲知要使用哪一個(gè)塊的內(nèi)容。
如果你想要多次打印一個(gè)塊,無論如何你可以使用特殊的 self 變量并調(diào)用與塊同名 的函數(shù):
<title>{% block title %}{% endblock %}</title>
<h1>{{ self.title() }}</h1>
{% block body %}{% endblock %}
可以調(diào)用 super 來渲染父級(jí)塊的內(nèi)容。這會(huì)返回父級(jí)塊的結(jié)果:
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ super() }}
{% endblock %}
Jinja2 允許你在塊的結(jié)束標(biāo)簽中加入的名稱來改善可讀性:
{% block sidebar %}
{% block inner_sidebar %}
...
{% endblock inner_sidebar %}
{% endblock sidebar %}
無論如何, endblock 后面的名稱一定與塊名匹配。
嵌套塊可以勝任更復(fù)雜的布局。而默認(rèn)的塊不允許訪問塊外作用域中的變量:
{% for item in seq %}
<li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}
這個(gè)例子會(huì)輸出空的 項(xiàng),因?yàn)?item 在塊中是不可用的。其原因是,如果 塊被子模板替換,變量在其塊中可能是未定義的或未被傳遞到上下文。
從 Jinja 2.2 開始,你可以顯式地指定在塊中可用的變量,只需在塊聲明中添加 scoped 修飾,就把塊設(shè)定到作用域中:
{% for item in seq %}
<li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
{% endfor %}
當(dāng)覆蓋一個(gè)塊時(shí),不需要提供 scoped 修飾。
當(dāng)一個(gè)模板對(duì)象被傳遞到模板上下文,你也可以從那個(gè)對(duì)象繼承。假設(shè)調(diào)用 代碼傳遞 layout_template 布局模板到環(huán)境,這段代碼會(huì)工作:
{% extends layout_template %}
之前 layout_template 變量一定是布局模板文件名的字符串才能工作。
當(dāng)從模板生成 HTML 時(shí),始終有這樣的風(fēng)險(xiǎn):變量包含影響已生成 HTML 的字符。有兩種 解決方法:手動(dòng)轉(zhuǎn)義每個(gè)字符或默認(rèn)自動(dòng)轉(zhuǎn)義所有的東西。
Jinja 兩者都支持,使用哪個(gè)取決于應(yīng)用的配置。默認(rèn)的配置未開啟自動(dòng)轉(zhuǎn)義有這樣幾個(gè) 原因:
如果啟用了手動(dòng)轉(zhuǎn)義,按需轉(zhuǎn)義變量就是 你的 責(zé)任。要轉(zhuǎn)義什么?如果你有 一個(gè) 可能 包含 > 、 < 、 & 或 " 字符的變量,你必須轉(zhuǎn)義 它,除非變量中的 HTML 有可信的良好格式。轉(zhuǎn)義通過用管道傳遞到過濾器 |e 來實(shí)現(xiàn): {{ user.username|e }} 。
當(dāng)啟用了自動(dòng)轉(zhuǎn)移,默認(rèn)會(huì)轉(zhuǎn)移一切,除非值被顯式地標(biāo)記為安全的。可以在應(yīng)用中 標(biāo)記,也可以在模板中使用 |safe 過濾器標(biāo)記。這種方法的主要問題是 Python 本 身沒有被污染的值的概念,所以一個(gè)值是否安全的信息會(huì)丟失。如果這個(gè)信息丟失, 會(huì)繼續(xù)轉(zhuǎn)義,你最后會(huì)得到一個(gè)轉(zhuǎn)義了兩次的內(nèi)容。
但雙重轉(zhuǎn)義很容易避免,只需要依賴 Jinja2 提供的工具而不使用諸如字符串模運(yùn)算符 這樣的 Python 內(nèi)置結(jié)構(gòu)。
返回模板數(shù)據(jù)(宏、 super 、 self.BLOCKNAME )的函數(shù),其返回值總是被標(biāo)記 為安全的。
模板中的字符串字面量在自動(dòng)轉(zhuǎn)義中被也被視為是不安全的。這是因?yàn)榘踩淖址?一個(gè)對(duì) Python 的擴(kuò)展,而不是每個(gè)庫都能妥善地使用它。
控制結(jié)構(gòu)指的是所有的那些可以控制程序流的東西 —— 條件(比如 if/elif/ekse )、 for 循環(huán)、以及宏和塊之類的東西??刂平Y(jié)構(gòu)在默認(rèn)語法中以 {% .. %} 塊的形式 出現(xiàn)。
遍歷序列中的每項(xiàng)。例如,要顯示一個(gè)由 users` 變量提供的用戶列表:
<h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
因?yàn)槟0逯械淖兞勘A羲鼈兊膶?duì)象屬性,可以迭代像 dict 的容器:
<dl>
{% for key, value in my_dict.iteritems() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
注意無論如何字典通常是無序的,所以你可能需要把它作為一個(gè)已排序的列表傳入 到模板或使用 dictsort 過濾器。
在一個(gè) for 循環(huán)塊中你可以訪問這些特殊的變量:
| 變量 | 描述 |
|---|---|
| loop.index | 當(dāng)前循環(huán)迭代的次數(shù)(從 1 開始) |
| loop.index0 | 當(dāng)前循環(huán)迭代的次數(shù)(從 0 開始) |
| loop.revindex | 到循環(huán)結(jié)束需要迭代的次數(shù)(從 1 開始) |
| loop.revindex0 | 到循環(huán)結(jié)束需要迭代的次數(shù)(從 0 開始) |
| loop.first | 如果是第一次迭代,為 True 。 |
| loop.last | 如果是最后一次迭代,為 True 。 |
| loop.length | 序列中的項(xiàng)目數(shù)。 |
| loop.cycle | 在一串序列間期取值的輔助函數(shù)。見下面的解釋。 |
在 for 循環(huán)中,可以使用特殊的 loop.cycle 輔助函數(shù),伴隨循環(huán)在一個(gè)字符串/變 量列表中周期取值:
{% for row in rows %}
<li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}
從 Jinja 2.1 開始,一個(gè)額外的 cycle 輔助函數(shù)允許循環(huán)限定外的周期取值。 更多信息請(qǐng)閱讀 全局函數(shù)清單 。
與 Python 中不同,模板中的循環(huán)內(nèi)不能 break 或 continue 。但你可以在迭代 中過濾序列來跳過項(xiàng)目。下面的例子中跳過了所有隱藏的用戶:
{% for user in users if not user.hidden %}
<li>{{ user.username|e }}</li>
{% endfor %}
好處是特殊的 loop 可以正確地計(jì)數(shù),從而不計(jì)入未迭代過的用戶。
如果因序列是空或者過濾移除了序列中的所有項(xiàng)目而沒有執(zhí)行循環(huán),你可以使用 else 渲染一個(gè)用于替換的塊:
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% else %}
<li><em>no users found</em></li>
{% endfor %}
</ul>
也可以遞歸地使用循環(huán)。當(dāng)你處理諸如站點(diǎn)地圖之類的遞歸數(shù)據(jù)時(shí)很有用。要遞歸地 使用循環(huán),你只需要在循環(huán)定義中加上 recursive 修飾,并在你想使用遞歸的地 方,對(duì)可迭代量調(diào)用 loop 變量。
下面的例子用遞歸循環(huán)實(shí)現(xiàn)了站點(diǎn)地圖:
<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>
Jinja 中的 if 語句可比 Python 中的 if 語句。在最簡(jiǎn)單的形式中,你可以測(cè)試 一個(gè)變量是否未定義,為空或 false:
{% if users %}
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}
像在 Python 中一樣,用 elif 和 else 來構(gòu)建多個(gè)分支。你也可以用更復(fù)雜的 表達(dá)式:
{% if kenny.sick %}
Kenny is sick.
{% elif kenny.dead %}
You killed Kenny! You bastard!!!
{% else %}
Kenny looks okay --- so far
{% endif %}
If 也可以被用作 內(nèi)聯(lián)表達(dá)式 并作為 循環(huán)過濾 。
宏類似常規(guī)編程語言中的函數(shù)。它們用于把常用行為作為可重用的函數(shù),取代 手動(dòng)重復(fù)的工作。
這里是一個(gè)宏渲染表單元素的小例子:
{% macro input(name, value='', type='text', size=20) -%}
<input type="{{ type }}" name="{{ name }}" value="{{
value|e }}" size="{{ size }}">
{%- endmacro %}
在命名空間中,宏之后可以像函數(shù)一樣調(diào)用:
<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>
如果宏在不同的模板中定義,你需要首先使用 import 。
在宏內(nèi)部,你可以訪問三個(gè)特殊的變量:
宏也可以暴露某些內(nèi)部細(xì)節(jié)。下面的宏對(duì)象屬性是可用的:
{{ input.name }} 會(huì)打印 input 。如果一個(gè)宏的名稱以下劃線開始,它不是導(dǎo)出的且不能被導(dǎo)入。
在某些情況下,需要把一個(gè)宏傳遞到另一個(gè)宏。為此,可以使用特殊的 call 塊。 下面的例子展示了如何讓宏利用調(diào)用功能:
{% 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 %}
也可以向調(diào)用塊傳遞參數(shù)。這在為循環(huán)做替換時(shí)很有用??偠灾?,調(diào)用塊的工作方 式幾乎與宏相同,只是調(diào)用塊沒有名稱。
這里是一個(gè)帶參數(shù)的調(diào)用塊的例子:
{% 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 %}
過濾器段允許你在一塊模板數(shù)據(jù)上應(yīng)用常規(guī) Jinja2 過濾器。只需要把代碼用 filter 節(jié)包裹起來:
{% filter upper %}
This text becomes uppercase
{% endfilter %}
在代碼塊中,你也可以為變量賦值。在頂層的(塊、宏、循環(huán)之外)賦值是可導(dǎo)出的,即 可以從別的模板中導(dǎo)入。
賦值使用 set 標(biāo)簽,并且可以為多個(gè)變量賦值:
{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
{% set key, value = call_something() %}
extends 標(biāo)簽用于從另一個(gè)模板繼承。你可以在一個(gè)文件中使用多次繼承,但是 只會(huì)執(zhí)行其中的一個(gè)。見上面的關(guān)于 模板繼承 的節(jié)。
塊用于繼承,同時(shí)作為占位符和用于替換的內(nèi)容。 模板繼承 節(jié)中詳細(xì)地介紹了塊。
include 語句用于包含一個(gè)模板,并在當(dāng)前命名空間中返回那個(gè)文件的內(nèi)容渲 染結(jié)果:
{% include 'header.html' %}
Body
{% include 'footer.html' %}
被包含的模板默認(rèn)可以訪問活動(dòng)的上下文中的變量。更多關(guān)于導(dǎo)入和包含的上下文 行為見 導(dǎo)入上下文行為 。
從 Jinja 2.2 開始,你可以把一句 include 用 ignore missing 標(biāo)記,這樣 如果模板不存在,Jinja 會(huì)忽略這條語句。當(dāng)與 with 或 without context 語句聯(lián)合使用時(shí),它必須被放在上下文可見性語句 之前 。這里是一些有效的例 子:
{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
你也可以提供一個(gè)模板列表,它會(huì)在包含前被檢查是否存在。第一個(gè)存在的模板會(huì) 被包含進(jìn)來。如果給出了 ignore missing ,且所有這些模板都不存在,會(huì)退化 至不做任何渲染,否則將會(huì)拋出一個(gè)異常。
例子:
{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
Changed in version 2.4: 如果傳遞一個(gè)模板對(duì)象到模板上下文,你可以用 include 包含這個(gè)對(duì) 象。
Jinja2 支持在宏中放置經(jīng)常使用的代碼。這些宏可以被導(dǎo)入,并不同的模板中使用。這 與 Python 中的 import 語句類似。要知道的是,導(dǎo)入量會(huì)被緩存,并且默認(rèn)下導(dǎo)入的 模板不能訪問當(dāng)前模板中的非全局變量。更多關(guān)于導(dǎo)入和包含的上下文行為見 導(dǎo)入上下文行為 。
有兩種方式來導(dǎo)入模板。你可以把整個(gè)模板導(dǎo)入到一個(gè)變量或從其中導(dǎo)入請(qǐng)求特定的宏 /導(dǎo)出量。
比如我們有一個(gè)渲染表單(名為 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 %}
最簡(jiǎn)單靈活的方式是把整個(gè)模塊導(dǎo)入為一個(gè)變量。這樣你可以訪問屬性:
{% 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>
此外你也可以從模板中導(dǎo)入名稱到當(dāng)前的命名空間:
{% 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>
名稱以一個(gè)或更多下劃線開始的宏和變量是私有的,不能被導(dǎo)入。
Changed in version 2.4: 如果傳遞一個(gè)模板對(duì)象到模板上下文,從那個(gè)對(duì)象中導(dǎo)入。
默認(rèn)下,每個(gè)包含的模板會(huì)被傳遞到當(dāng)前上下文,而導(dǎo)入的模板不會(huì)。這樣做的原因 是導(dǎo)入量不會(huì)像包含量被緩存,因?yàn)閷?dǎo)入量經(jīng)常只作容納宏的模塊。
無論如何,這當(dāng)然也可以顯式地更改。通過在 import/include 聲明中直接添加 with context 或 without context ,當(dāng)前的上下文可以傳遞到模板,而且不會(huì) 自動(dòng)禁用緩存。
這里有兩個(gè)例子:
{% from 'forms.html' import input with context %}
{% include 'header.html' without context %}
提示
在 Jinja 2.0 中,被傳遞到被包含模板的上下文不包含模板中定義的變量。 事實(shí)上,這不能工作:
{% for box in boxes %}
{% include "render_box.html" %}
{% endfor %}
在 Jinja 2.0 中,被包含的模板 render_box.html 不能 訪問 box 。從 Jinja 2.1 開始, render_box.html 可以 這么做。
Jinja 中到處都允許使用基本表達(dá)式。這像常規(guī)的 Python 一樣工作,即使你不用 Python 工作,你也會(huì)感受到其帶來的便利。
表達(dá)式最簡(jiǎn)單的形式就是字面量。字面量表示諸如字符串和數(shù)值的 Python 對(duì)象。下面 的字面量是可用的:
42 和 42.0 是不一樣的。一對(duì)中括號(hào)括起來的東西是一個(gè)列表。列表用于存儲(chǔ)和迭代序列化的數(shù)據(jù)。例如 你可以容易地在 for 循環(huán)中用列表和元組創(chuàng)建一個(gè)鏈接的列表:
<ul>
{% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
('downloads.html', 'Downloads')] %}
<li><a href="{{ href }}">{{ caption }}</a></li>
{% endfor %}
</ul>
xmlattr() 過濾器之類。提示
特殊常量 true 、 false 和 none 實(shí)際上是小寫的。因?yàn)檫@在過去會(huì)導(dǎo)致 混淆,過去 True 擴(kuò)展為一個(gè)被認(rèn)為是 false 的未定義的變量。所有的這三個(gè) 常量也可以被寫成首字母大寫( True 、 False 和 None )。盡管如此, 為了一致性(所有的 Jinja 標(biāo)識(shí)符是小寫的),你應(yīng)該使用小寫的版本。
Jinja 允許你用計(jì)算值。這在模板中很少用到,但是為了完整性允許其存在。支持下面的 運(yùn)算符:
~ 運(yùn)算符。 {{ 1 + 1 }} 等于 2 。{{ 3 - 2 }} 等于 1 。{{ 1 / 2 }} 等于 {{ 0.5 }} 。{{ 20 // 7 }} 等于 2 。{{ 11 % 7 }} 等于 4 。{{ 2 * 2 }} 會(huì)返回 4 。也可以用于重 復(fù)一個(gè)字符串多次。 {{ '=' * 80 }} 會(huì)打印 80 個(gè)等號(hào)的橫條。{{ 2**3 }} 會(huì)返回 8 。: 如果左邊大于右邊,返回 true 。
- =
- 如果左邊大于等于右邊,返回 true 。
對(duì)于 if 語句,在 for 過濾或 if 表達(dá)式中,它可以用于聯(lián)合多個(gè)表達(dá)式:
提示
is 和 in 運(yùn)算符同樣支持使用中綴記法: foo is not bar 和 foo not in bar 而不是 not foo is bar 和 not foo in bar 。所有的 其它表達(dá)式需要前綴記法 not (foo and bar) 。
下面的運(yùn)算符非常有用,但不適用于其它的兩個(gè)分類:
{{ 1 in [1,2,3] }} 會(huì)返回 true 。{{ "Hello " ~ name ~ "!" }} 會(huì)返回(假設(shè) name 值為 ''John' ) Hello John! 。{{ post.render() }} 。在圓括號(hào)中,你可以像在 python 中一樣使用位置參數(shù)和關(guān)鍵字參數(shù): {{ post.render(user, full=true) }} 。同樣,也可以使用內(nèi)聯(lián)的 if 表達(dá)式。這在某些情況很有用。例如你可以用來在一個(gè) 變量定義的情況下才繼承一個(gè)模板,否則繼承默認(rèn)的布局模板:
{% extends layout_template if layout_template is defined else 'master.html' %}
一般的語法是 if else 。
else 部分是可選的。如果沒有顯式地提供 else 塊,會(huì)求值一個(gè)未定義對(duì)象:
{{ '[%s]' % page.title if page.title }}
abs(number)Return the absolute value of the argument.
attr(obj, name)Get an attribute of an object. foo|attr("bar") works like foo["bar"] just that always an attribute is returned and items are not looked up.
See Notes on subscriptions for more details.
batch(value, linecount, _fillwith=None)A filter that batches items. It works pretty much like slice just the other way round. It returns a list of lists with the given number of items. If you provide a second parameter this is used to fill up missing items. See this example:
<table>
{%- for row in items|batch(3, ' ') %}
<tr>
{%- for column in row %}
<td>{{ column }}</td>
{%- endfor %}
</tr>
{%- endfor %}
</table>
capitalize(s)Capitalize a value. The first character will be uppercase, all others lowercase.
center(value, width=80)Centers the value in a field of a given width.
default(value, _defaultvalue=u'', boolean=False)If the value is undefined it will return the passed default value, otherwise the value of the variable:
{{ my_variable|default('my_variable is not defined') }}
This will output the value of my_variable if the variable was defined, otherwise 'my_variable is not defined'. If you want to use default with variables that evaluate to false you have to set the second parameter to true:
{{ ''|default('the string was empty', true) }}
dictsort(value, _casesensitive=False, by='key')Sort a dict and yield (key, value) pairs. Because python dicts are unsorted you may want to use this function to order them by either key or value:
{% for item in mydict|dictsort %}
sort the dict by key, case insensitive
{% for item in mydict|dictsort(true) %}
sort the dict by key, case sensitive
{% for item in mydict|dictsort(false, 'value') %}
sort the dict by key, case insensitive, sorted
normally and ordered by value.
escape(s)Convert the characters &, <, >, ', and " in string s to HTML-safe sequences. Use this if you need to display text that might contain such characters in HTML. Marks return value as markup string.
filesizeformat(value, binary=False)Format the value like a 'human-readable' file size (i.e. 13 kB, 4.1 MB, 102 Bytes, etc). Per default decimal prefixes are used (Mega, Giga, etc.), if the second parameter is set to True the binary prefixes are used (Mebi, Gibi).
first(seq)Return the first item of a sequence.
float(value, default=0.0)Convert the value into a floating point number. If the conversion doesn't work it will return 0.0. You can override this default using the first parameter.
forceescape(value)Enforce HTML escaping. This will probably double escape variables.
format(value, *args, **kwargs)Apply python string formatting on an object:
{{ "%s - %s"|format("Hello?", "Foo!") }}
-> Hello? - Foo!
groupby(value, attribute)Group a sequence of objects by a common attribute.
If you for example have a list of dicts or objects that represent persons with gender, first_name and last_name attributes and you want to group all users by genders you can do something like the following snippet:
<ul>
{% for group in persons|groupby('gender') %}
<li>{{ group.grouper }}<ul>
{% for person in group.list %}
<li>{{ person.first_name }} {{ person.last_name }}</li>
{% endfor %}</ul></li>
{% endfor %}
</ul>
Additionally it's possible to use tuple unpacking for the grouper and list:
<ul>
{% for grouper, list in persons|groupby('gender') %}
...
{% endfor %}
</ul>
As you can see the item we're grouping by is stored in the grouper attribute and the list contains all the objects that have this grouper in common.
Changed in version 2.6: It's now possible to use dotted notation to group by the child attribute of another attribute.
indent(s, width=4, indentfirst=False)Return a copy of the passed string, each line indented by 4 spaces. The first line is not indented. If you want to change the number of spaces or indent the first line too you can pass additional parameters to the filter:
{{ mytext|indent(2, true) }}
indent by two spaces and indent the first line too.
int(value, default=0)Convert the value into an integer. If the conversion doesn't work it will return 0. You can override this default using the first parameter.
join(value, d=u'', attribute=None)Return a string which is the concatenation of the strings in the sequence. The separator between elements is an empty string per default, you can define it with the optional parameter:
{{ [1, 2, 3]|join('|') }}
-> 1|2|3
{{ [1, 2, 3]|join }}
-> 123
It is also possible to join certain attributes of an object:
{{ users|join(', ', attribute='username') }}
New in version 2.6: The attribute parameter was added.
last(seq)Return the last item of a sequence.
length(object)Return the number of items of a sequence or mapping.
list(value)Convert the value into a list. If it was a string the returned list will be a list of characters.
lower(s)Convert a value to lowercase.
map()Applies a filter on a sequence of objects or looks up an attribute. This is useful when dealing with lists of objects but you are really only interested in a certain value of it.
The basic usage is mapping on an attribute. Imagine you have a list of users but you are only interested in a list of usernames:
Users on this page: {{ users|map(attribute='username')|join(', ') }}
Alternatively you can let it invoke a filter by passing the name of the filter and the arguments afterwards. A good example would be applying a text conversion filter on a sequence:
Users on this page: {{ titles|map('lower')|join(', ') }}
pprint(value, verbose=False)Pretty print a variable. Useful for debugging.
With Jinja 1.2 onwards you can pass it a parameter. If this parameter is truthy the output will be more verbose (this requires pretty)
random(seq)Return a random item from the sequence.
reject()Filters a sequence of objects by appying a test to either the object or the attribute and rejecting the ones with the test succeeding.
Example usage:
{{ numbers|reject("odd") }}
rejectattr()Filters a sequence of objects by appying a test to either the object or the attribute and rejecting the ones with the test succeeding.
{{ users|rejectattr("is_active") }}
{{ users|rejectattr("email", "none") }}
replace(s, old, new, count=None)Return a copy of the value with all occurrences of a substring replaced with a new one. The first argument is the substring that should be replaced, the second is the replacement string. If the optional third argument count is given, only the first count occurrences are replaced:
{{ "Hello World"|replace("Hello", "Goodbye") }}
-> Goodbye World
{{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
-> d'oh, d'oh, aaargh
reverse(value)Reverse the object or return an iterator the iterates over it the other way round.
round(value, precision=0, method='common')Round the number to a given precision. The first parameter specifies the precision (default is 0), the second the rounding method:
'common' rounds either up or down'ceil' always rounds up'floor' always rounds downIf you don't specify a method 'common' is used.
{{ 42.55|round }}
-> 43.0
{{ 42.55|round(1, 'floor') }}
-> 42.5
Note that even if rounded to 0 precision, a float is returned. If you need a real integer, pipe it through int:
{{ 42.55|round|int }}
-> 43
safe(value