Flask和Django,以及其它不少Python框架如Ansible,都默認使用Jinja2來做爲模版引擎。咱們用Jinja2在服務器上直接生成配置和其餘文件。 Jinja是一個基於Python設計語言的「全功能模板引擎」,我的認爲Jinja語法自己並不複雜,但掌握好基本的Jinja語法會幫助你在構建Ansible、Jenkins、Web等批處理做業時作到事半功倍的效果。html
模板引擎Jinja2語法介紹
2020年02月20日 - 初稿python
閱讀原文 - https://wsgzao.github.io/post...nginx
Jinja is a modern and designer-friendly templating language for Python, modelled after Django’s templates. It is fast, widely used and secure with the optional sandboxed template execution environment:git
{% extends "base.html" %} {% block title %}Members{% endblock %} {% block content %} <ul> {% for user in users %} <li><a href="{{ user.url }}">{{ user.username }}</a></li> {% endfor %} </ul> {% endblock %}
Features:github
Jinja2 是一個現代的,設計者友好的,仿照 Django 模板的 Python 模板語言。 它速度快,被普遍使用,而且提供了可選的沙箱模板執行環境保證安全:express
特性:flask
爲何要叫Jinja?
之因此叫Jinja,是由於日本的神社(Jinja)英文單詞是temple,而模板的英文是template,二者發音很類似(這麼說來,它原本也有可能叫Miao的……)。segmentfault
Jinja的速度怎麼樣?
和Mako差很少,但比Genshi以及Django的模板引擎快10~20倍。api
把邏輯判斷(Logic)放到模板裏是個好主意嗎?
毫無疑問,你放到模板裏邏輯判斷(Logic)應該越少越好。但爲了讓你們都開心,適當的邏輯判斷是須要的。儘管如此,它有不少對於你能作什麼,不能作什麼的限制。安全
出於諸多考慮(速度,易讀性等等),Jinja既不容許你放置任意的Python代碼,也不容許全部的Python表達式。這也是爲何咱們要了解Jinja2的語法。
在Jinja官方文檔中建議你們能夠優先閱讀如下2個章節:
在Python中,什麼是模版?就是在一個靜態HTML加入一些相似變量的標籤,而後引擎在渲染這個HTML時候會動態的把變量填入內容,生成一個最終的HTML。
什麼是模版引擎?其實就是一種能解析相似Python語言
的標記語言的解釋器。
好比咱們在HTML模版中輸入一個`<p> {{ post.title }} </p>`,顯然這不是真正的HTML語法。可是當Jinja2解釋器讀取到`{{ ...}}`後知道里面是一個變量,那麼就把這個變量替換爲真正的值,最後翻譯出來就變成了`<p> 大標題 </p>`這樣的HTML內容。
Jinja2是一個模版語言,只是相似Python,比較符合Python語法,但不徹底相同!
全部的模版引擎,實際上都差很少,不論是基於VBS語言的ASP模版,仍是基於PHP語言的PHP模版,都不是與本來語言一摸同樣,而只是作到儘可能同樣而已。
注意:Jinja2
模版語言,是不區分縮進的,和純python不一樣。實際上全部模版語言都不區分縮緊。
經常使用標記:
註釋:`{# 這是註釋 #}` 變量:`{{ post.title }}`,或字典元素`{{your_dict['key']}}`,或列表`{{your_list[0]}}` 多行代碼塊:`{% 開始 %} HTML標籤 {% 結束 %}`
示例:
{% if user %} {{ user }} {% else %} hello! {% for index in indexs %} {{ index }} {% endfor %}
{% … %} 語句([Statements](http://jinja.pocoo.org/docs/dev/templates/#list-of-control-structures)) {{ … }} 打印模板輸出的表達式([Expressions](http://jinja.pocoo.org/docs/dev/templates/#expressions)) {# … #} 註釋 # … ## 行語句([Line Statements](http://jinja.pocoo.org/docs/dev/templates/#line-statements))
除了普通的字符串變量,Jinja2還支持列表、字典和對象,你能夠這樣獲取變量值:
{{ mydict['key'] }} {{ mylist[3] }} {{ mylist[myintvar] }} {{ myobj.somemethod() }}
獲取一個變量的屬性有兩種方式:
{{ foo.bar }} {{ foo['bar'] }}
這兩種方法基本相同(深層次的區別能夠暫不考慮)
一個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提供的tests能夠用來在語句裏對變量或表達式進行測試,若是要測試一個變量,能夠在變量後加上「is」和test名,好比:
{% if user.age is equalto 42 %} {# 這裏也能夠寫成... is equalto(42) #} Ha, you are 42! {% endif %}
若是要傳入參數,能夠在test後增長括號,也能夠直接寫在後面。
經常使用的test(未說明的均返回True或False):
A control structure refers to all those things that control the flow of a program - conditionals (i.e. if/elif/else), for-loops, as well as things like macros and blocks. With the default syntax, control structures appear inside blocks.
Loop over each item in a sequence. For example, to display a list of users provided in a variable called users:
<h1>Members</h1> <ul> {% for user in users %} <li>{{ user.username|e }}</li> {% endfor %} </ul>
As variables in templates retain their object properties, it is possible to iterate over containers like dict:
<dl> {% for key, value in my_dict.items() %} <dt>{{ key|e }}</dt> <dd>{{ value|e }}</dd> {% endfor %} </dl>
循環索引
The if statement in Jinja is comparable with the Python if statement. In the simplest form, you can use it to test if a variable is defined, not empty and not false:
{% if users %} <ul> {% for user in users %} <li>{{ user.username|e }}</li> {% endfor %} </ul> {% endif %}
For multiple branches, elif and else can be used like in Python. You can use more complex Expressions there, too:
{% if kenny.sick %} Kenny is sick. {% elif kenny.dead %} You killed Kenny! You bastard!!! {% else %} Kenny looks okay --- so far {% endif %}
更多用法能夠閱讀參考文章中的連接
variables: 能夠輸出數據
{{ my_variable }} {{ some_dudes_name | capitalize }}
statements: 能夠用來建立條件和循環等等
{% if my_conditional %} xxx {% endif %} {% for item in all_items %} {{ item }} {% endfor %}
從上文中第二個variable的例子中能夠看出,Jinja2支持使用帶過濾器的Unix型管道操做符。有不少的內置過濾器可供使用。
咱們能夠僅僅用一堆簡單if和for就能夠創建創建幾乎任何的常規配置文件。不過若是你有意更進一步,Jinja2 Documentation包含了不少有趣的東西可供瞭解。咱們能夠看到Ansibe容許在模板中使用一些額外的模版變量。
按照Ansible template_module, 咱們模板的示例:
- name: Create Nginx SSL configuration template: src: "nginx_ssl.j2" dest: "/etc/nginx/sites-available/{{ project_name }}"
咱們一樣能夠發如今Ansible Facts中有不少可用的Ansible變量。