Flask模板引擎:Jinja2語法介紹

Jinja是組成Flask的模板引擎。可能你還不太了解它是幹嘛的,但你對下面這些百分號和大括弧肯定不陌生:

{% block body %} <ul> {% for user in users %} <li><a href="{{ user.url }}">{{ user.username }}</a></li> {% endfor %} </ul>{% endblock %}

看過《Flask Web開發》,很多人都能寫出來這些,但除了書里講的,你還應該了解一些其他的語法細節。這篇文章就來介紹一些常用的語法和函數,如果想要系統完整的了解Jinja,可以去讀它的文檔:Jinja2 Documentation。

FAQ

在Jinja網站上的FAQ里,我挑了三個大家可能會比較感興趣的問題(簡單翻譯了一下)。

1、為什麼要叫Jinja?

之所以叫Jinja,是因為日本的神社(Jinja)英文單詞是temple,而模板的英文是template,兩者發音很相似(這麼說來,它本來也有可能叫Miao的……)。

2、Jinja的速度怎麼樣?

和Mako差不多,但比Genshi以及Django的模板引擎快10~20倍。

3、把邏輯判斷(Logic)放到模板里是個好主意嗎?

毫無疑問,你放到模板里邏輯判斷(Logic)應該越少越好。但為了讓大家都開心,適當的邏輯判斷是需要的。儘管如此,它有很多對於你能做什麼,不能做什麼的限制。

出於諸多考慮(速度,易讀性等等),Jinja既不允許你放置任意的Python代碼,也不允許所有的Python表達式。這也是為什麼我們要了解Jinja2的語法。

Delimiters(分隔符)

  • {% ... %} 語句(Statements)
  • {{ ... }} 列印模板輸出的表達式(Expressions)
  • {# ... #} 注釋
  • # ... ## 行語句(Line Statements)

多說一下注釋,這是單行注釋:

{#% for user in users %#}

下面是多行注釋:

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

Variables(變數)

除了普通的字元串變數,Jinja2還支持列表、字典和對象,你可以這樣獲取變數值:

{{ mydict[key] }}{{ mylist[3] }}{{ mylist[myintvar] }}{{ myobj.somemethod() }}

獲取一個變數的屬性有兩種方式:

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

這兩種方法基本相同(深層次的區別可以暫不考慮)

Filter(過濾器)

過濾器用來修改變數,使用一個豎線和變數相隔。

{{ items|join(, ) }}

常用的內置過濾器:

  • safe 渲染時不轉義

  • capitalize 首字母大寫
  • lower 小寫
  • upper 大寫
  • title 每個單詞的首字母都轉換成大寫
  • trim 去掉首尾空格
  • striptags 去掉值里的HTML標籤
  • default 設置一個默認值,如果變數未定義,就用這個默認值替換。類似這樣:

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

  • random(seq) 返回一個序列里的隨機元素

  • truncate(s, length=255, killwords=False, end=...) 截取出指定長度的文章(文章摘要)

  • format(value, *args, **kwargs) 參考Python的字元串格式化函數

  • length 左邊如果是列表,輸出列表的數量;如果是字元串,則輸出字元串的長度
  • ……

完整的fliter列表:jinja.pocoo.org/docs/de

Tests(測試,判斷)

Jinja2提供的tests可以用來在語句里對變數或表達式進行測試,如果要測試一個變數,可以在變數後加上「is」和test名,比如:

{% if user.age is equalto 42 %} {# 這裡也可以寫成... is equalto(42) #} Ha, you are 42!{% endif %}

如果要傳入參數,可以在test後增加括弧,也可以直接寫在後面

常用的test(未說明的均返回True或False):

  • defined

  • equalto

  • escaped

  • none

  • sequence

  • string

  • number
  • reverse
  • replace
  • ......

完整的test列表及用法見:Template Designer Documentation

Loop(循環)

在一個for循環內,有一些特殊的變數可以使用,這是幾個常用的:

  • loop.index 當前迭代數,可以用來寫評論的樓層數(從1開始)

  • loop.index0 同上,不過從0開始迭代

  • loop.revindex 反向的迭代數(基數為1)

  • loop.revindex0 反向的迭代數(基數為0)

  • loop.length 序列的數量

  • loop.first 是否是第一個元素

  • loop.last 是否是最後一個元素

  • ......

完整的列表見:jinja.pocoo.org/docs/de

Whitespace Control(空格控制)

默認的設置:

  1. 如果末尾有換行符,則去除;
  2. 其他空格原樣保留。

也就是說,下面這幾行:

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

渲染後的結果是這樣:

<div> yay</div>

Jinja2語句佔據的空行,你自己輸出的空格,Tab都將保留。

如果要去掉Jinja2語句佔據的空行,可以通過設置Jinja2的環境變數實現:

app.jinja_env.trim_blocks = Trueapp.jinja_env.lstrip_blocks = True

或者像這樣手動添加一個減號(注意和%之間沒有空格):

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

兩者實現的效果相同,如下:

<div> yay</div>

如果語句塊的前後都加上減號:

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

渲染後會是這樣:

<div>yay</div>

通過Jinja2提供的環境變數,你可以設置很多東西,比如分隔符(在和其他的語言產生衝突時,可以通過修改分隔符來解決)。具體見:jinja.pocoo.org/docs/de

Escaping(轉義)

有時你會想原樣輸出一些Jinja2語句和分隔符,對於小的內容,可以使用變數表達式來輸出,比如輸出一個分隔符:

{{ {{ }}

大的內容塊可以使用一個raw塊包裹:

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

模板繼承

你可以創建一個base.html作為基模板,把導航欄、頁腳、flash消息、js或css文件等等需要在每一個頁面中顯示的內容放在基模板里,並添加一個空的塊用來放置其他子模板的內容:

{% block content %}{% endblock %}

然後在其他的模板(子模板)里使用這個extends語句繼承它,並放置相應的內容到基模板里定義過的空塊:

{% extends "base.html" %}{% block content %} 子模板的內容{% endblock %}

如果想添加內容到在父模板內已經定義的塊,可以使用super函數:

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

這樣可以避免覆蓋父塊的內容。

全局函數

常用的全局函數有:

  • range([start, ]stop[, step])
  • lipsum(n=5, html=True, min=20, max=100) 為模板生成一些 lorem ipsum。

詳細列表見:Template Designer Documentation

其他內容

內容還有很多,比如行語句、控制流、表達式、宏等。不再一一介紹了(寫這種介紹文章太累了……)。

具體見文檔的模板部分:

Template Designer Documentation

相關鏈接

Jinja主頁:Jinja2 Documentation

Jinja2文檔:Jinja2 Documentation

Jinja2文檔模板部分:Template Designer Documentation

Github項目頁:pallets/jinja

- - - - -

更多關於Flask和Web開發的優質原創內容,歡迎關注Hello, Flask! - 知乎專欄。

推薦閱讀:

OpenCV:圖片操作基本知識(二)
數據分析入門必看案例:泰坦尼克號倖存率研究
深入淺出區塊鏈(1)介紹
基於TCP的python聊天程序
學會最簡單的資料庫|看完這7招就夠了

TAG:Python | Flask | Web开发 |