一篇文章搞懂Jinja2 Template Engine 模版引擎

Flask和Django,以及其它不少Python框架,都默認使用Jinja2來做爲模版引擎。html

在Python中,什麼是模版?就是在一個靜態HTML加入一些相似變量的標籤,而後引擎在渲染這個HTML時候會動態的把變量填入內容,生成一個最終的HTML。
什麼是模版引擎?其實就是一種能解析相似Python語言的標記語言的解釋器。python

好比咱們在HTML模版中輸入一個<p> {{ post.title }} </p>,顯然這不是真正的HTML語法。可是當Jinja2解釋器讀取到{{ ...}}後知道里面是一個變量,那麼就把這個變量替換爲真正的值,最後翻譯出來就變成了<p> 大標題 </p>這樣的HTML內容。api

Jinja2是一個模版語言,只是相似Python,比較符合Python語法,但不徹底相同!app

全部的模版引擎,實際上都差很少,不論是基於VBS語言的ASP模版,仍是基於PHP語言的PHP模版,都不是與本來語言一摸同樣,而只是作到儘可能同樣而已。框架

Jinja2語言基礎

注意:Jinja2模版語言,是不區分縮進的,和純python不一樣。實際上全部模版語言都不區分縮緊。函數

經常使用標記:post

  • 註釋:{# 這是註釋 #}
  • 變量:{{ post.title }},或字典元素{{your_dict['key']}},或列表{{your_list[0]}}
  • 多行代碼塊:{% 開始 %} HTML標籤 {% 結束 %}

示例:url

{% if user %}
    {{ user }}
{% else %}
    hello!
    {% for index in indexs %}
        {{ index }} 
{% endfor %}

Jinja2 Filter 過濾器 (即函數)

一個filter過濾器的本質就是一個function函數。使用格式爲:變量名 | 函數
它作到的就是,把變量傳給函數,而後再把函數返回值做爲這個代碼塊的值。命令行

如:翻譯

<!-- 帶參數的 -->
{{變量 | 函數名(*args)}}

<!-- 不帶參數能夠省略括號 -->
{{變量 | 函數名}}

鏈式調用(管道式):
和命令行的pipline管道同樣,能夠一次調用多個函數(過濾器),如:

{{ "hello world" | reverse | upper }}

文本塊調用(將中間的全部文字都做爲變量內容傳入到過濾器中):

{% filter upper %}
    一大堆文字
{% endfilter %}

Jinja2經常使用內置函數(過濾器)

字符串操做:

safe:禁用轉義
<p>{{ '<em>hello</em>' | safe }}</p>

capitalize:把變量值的首字母轉成大寫,其他字母轉小寫
<p>{{ 'hello' | capitalize }}</p>

lower:把值轉成小寫
<p>{{ 'HELLO' | lower }}</p>

upper:把值轉成大寫
<p>{{ 'hello' | upper }}</p>

title:把值中的每一個單詞的首字母都轉成大寫
<p>{{ 'hello' | title }}</p>

reverse:字符串反轉
<p>{{ 'olleh' | reverse }}</p>

format:格式化輸出
<p>{{ '%s is %d' | format('name',17) }}</p>

striptags:渲染以前把值中全部的HTML標籤都刪掉
<p>{{ '<em>hello</em>' | striptags }}</p>

truncate: 字符串截斷
<p>{{ 'hello every one' | truncate(9)}}</p>

列表操做:

first:取第一個元素
<p>{{ [1,2,3,4,5,6] | first }}</p>

last:取最後一個元素
<p>{{ [1,2,3,4,5,6] | last }}</p>

length:獲取列表長度
<p>{{ [1,2,3,4,5,6] | length }}</p>

sum:列表求和
<p>{{ [1,2,3,4,5,6] | sum }}</p>

sort:列表排序
<p>{{ [6,2,3,1,5,4] | sort }}</p>

Jinja2 Macro 宏 (自定義函數)

Jinja2是容許自定義函數的,這樣在模版中能夠重複利用這個自定義函數。Jinja2稱之爲Macro宏。

定義方法:

{% macro 函數名(參數) %}
    具體的HTML內容
{% endmacro %}

<!-- 使用 -->
{{ 函數名(參數) }}

<!-- 或做爲過濾器 -->
{{ 變量 | 函數名(參數) }}

關於Jinja2自定義函數的context上下文和環境變量的問題:
Jinja2的自定義函數「宏」,自己是無法像filter過濾器函數同樣使用上下文和環境變量的。
不過能夠加上@contextfilter裝飾器達到一樣的效果。

導入另外一個文件的自定義函數「宏」:
假設在macro.html文件中咱們定義了一個函數func()
那麼如今咱們能夠在另外一個文件reference.html中像python導入模塊同樣導入它:

{% import 'macro.html' as module %}
{{ module.func() }}

Include 模版引用

Include是咱們經常使用的操做,即定義一個框架模版(父模版),而後一個一個指定性的把子模版引入進來。

框架模版frame.html以下:

{% include 'header.html' %}

{% include 'body.html' %}

{% include 'footer.html' %}

Extend 模版繼承

咱們能夠在一個父模版中定義一個block代碼塊,而後在另外一個子模版中「繼承」這個父模版,並重寫這個block代碼塊。
不過通常模版中的父模版,都只是留出一個block空位,裏面不寫東西,特地等子模版來實現。

假設如今有一個父模版parent.html

{% block HEADER %}
    頁頭部分的HTML內容。
{% endblock HEADER %}

{% block BODY %}
    正文部分的HTML內容。
{% endblock BODY %}

{% block FOOTER %}
    頁腳部分的HTML內容。
{% endblock FOOTER %}

其中定義了三個block,頁頭、正文和頁腳。

而後咱們就能夠定義一個模版child.html來繼承父模版,而且只重寫BODY部分:

{% extends 'parent.html' %}
{% block BODY %}
    由子頁面重寫改寫的的HTML內容,替換父頁面的BODY。。。
{% endblock BODY %}

擴展完成後,咱們最終獲得的結果是:

{% block HEADER %}
    頁頭部分的HTML內容。
{% endblock HEADER %}

{% block BODY %}
    由子頁面重寫改寫的的HTML內容,替換父頁面的BODY。。。
{% endblock BODY %}

{% block FOOTER %}
    頁腳部分的HTML內容。
{% endblock FOOTER %}

Jinja2模版引用Flask路由中的內容

在Flask應用Jinja2模版時,在模版中能夠直接調用Flask app中的一些公用變量和方法。

引用Flask的request對象:

<p> {{ request.url }} </p>
<p> {{ request.form.get('name') }} </p>

引用Flask的url_for(...)方法:

<!-- 它會返回咱們定義的路由`app.route('/index')`所對應的URL -->
<p> {{ url_for('index') }} </p>

<!-- 它會返回咱們定義的路由`app.route('/post/{post_id}')`所對應的URL -->
<p> {{ url_for('post', post_id='127') }} </p>

在模版中,咱們能夠引用get_flashed_messages()方法,獲取Flask路由傳來的閃現信息

{% for msg in get_flashed_messages() %}
    <p> {{ msg }} </p>
{% endfor %}

這種閃現信息是從Flask路由中傳來的,只要在路由中發一個flash('hello')信息,至關於彈了一個alert()。而後咱們能夠在Jinja2的模版中用get_flashed_messages()得到flash過來的信息列表。

相關文章
相關標籤/搜索