模板
要了解jinja2,,那么需要先理解模板的概念,。模板在Python的web開發(fā)中廣泛使用,,它能夠有效的將業(yè)務(wù)邏輯和頁面邏輯分開,使代碼可讀性增強,、并且更加容易理解和維護(hù),。
模板簡單來說就是一個其中包涵占位變量表示動態(tài)的部分的文件,模板文件在經(jīng)過動態(tài)賦值后,,返回給用戶,。 --> 可以理解為渲染
python中自帶一個簡單的模板,就是string提供的,。
1 2 3 4 5 6 7 | >>> import string
>>> a = string.Template( '$who is $role' )
>>> a.substitute(who = 'daxin' ,role = 'Linux' )
'daxin is Linux'
>>> a.substitute(who = 'daxin' ,role = 'cat' )
'daxin is cat'
>>>
|
Python自帶的模板功能極其有限,,如果我們想要在模板中使用控制語句,和表達(dá)式,,以及繼承等功能的話,,就無法實現(xiàn)了。
目前主流的模板系統(tǒng),,最常用的就是jinja2和mako
jinja2介紹
jinja2是Flask作者開發(fā)的一個模板系統(tǒng),,起初是仿django模板的一個模板引擎,為Flask提供模板支持,,由于其靈活,,快速和安全等優(yōu)點被廣泛使用。
jinja2的優(yōu)點
jinja2之所以被廣泛使用是因為它具有以下優(yōu)點:
- 相對于Template,,jinja2更加靈活,,它提供了控制結(jié)構(gòu),表達(dá)式和繼承等,。
- 相對于Mako,,jinja2僅有控制結(jié)構(gòu),不允許在模板中編寫太多的業(yè)務(wù)邏輯,。
- 相對于Django模板,,jinja2性能更好。
- Jinja2模板的可讀性很棒,。
安裝jinja2
由于jinja2屬于第三方模塊,,首先需要對其進(jìn)行安裝
測試模板是否安裝成功
1 2 3 4 | python - c "import jinja2"
# 沒有報錯就表示安裝成功
# 必須用雙引號"
|
jinja2語法
作為一個模板系統(tǒng),它還提供了特殊的語法,,我們按照它支持的語法進(jìn)行編寫之后,,就能使用jinja2模塊進(jìn)行渲染。
基本語法
在jinja2中,,存在三種語法:
- 控制結(jié)構(gòu) {% %}
- 變量取值 {{ }}
- 注釋 {# #}
下面是一個簡單的jinja2例子
1 2 3 4 5 6 7 | {# This is jinja code
{% for file in filenames %}
...
{% endfor %}
#}
|
可以看到,,for循環(huán)的使用方式和Python比較類似,但是沒有了句尾的冒號,,另外需要使用endfor最為結(jié)尾,,其實在jinja2中,,if也是一樣的,結(jié)尾需要使用endif,。
jinja2變量
jinja2模板中使用 {{ }} 語法表示一個變量,,它是一種特殊的占位符。當(dāng)利用jinja2進(jìn)行渲染的時候,,它會把這些特殊的占位符進(jìn)行填充/替換,,jinja2支持python中所有的Python數(shù)據(jù)類型比如列表、字段,、對象等,。
1 2 3 | <p>this is a dicectory:{{ mydict[ 'key' ] }} </p>
<p>this is a list:{{ mylist[3] }} </p>
<p>this is a object:{{ myobject.something() }} </p>
|
jinja2中的過濾器
變量可以通過“過濾器”進(jìn)行修改,過濾器可以理解為是jinja2里面的內(nèi)置函數(shù)和字符串處理函數(shù),。
常用的過濾器有:
過濾器名稱 |
說明 |
safe |
渲染時值不轉(zhuǎn)義 |
capitialize |
把值的首字母轉(zhuǎn)換成大寫,,其他子母轉(zhuǎn)換為小寫 |
lower |
把值轉(zhuǎn)換成小寫形式 |
upper |
把值轉(zhuǎn)換成大寫形式 |
title |
把值中每個單詞的首字母都轉(zhuǎn)換成大寫 |
trim |
把值的首尾空格去掉 |
striptags |
渲染之前把值中所有的HTML標(biāo)簽都刪掉 |
join |
拼接多個值為字符串 |
replace |
替換字符串的值 |
round |
默認(rèn)對數(shù)字進(jìn)行四舍五入,也可以用參數(shù)進(jìn)行控制 |
int |
把值轉(zhuǎn)換成整型 |
那么如何使用這些過濾器呢,? 只需要在變量后面使用管道(|)分割,,多個過濾器可以鏈?zhǔn)秸{(diào)用,前一個過濾器的輸出會作為后一個過濾器的輸入,。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | {{ 'abc' | captialize }}
# Abc
{{ 'abc' | upper }}
# ABC
{{ 'hello world' | title }}
# Hello World
{{ "hello world" | replace( 'world' , 'daxin' ) | upper }}
# HELLO DAXIN
{{ 18.18 | round | int }}
# 18
|
jinja2的控制結(jié)構(gòu)
jinja2中的if語句類似與Python的if語句,,它也具有單分支,多分支等多種結(jié)構(gòu),,不同的是,,條件語句不需要使用冒號結(jié)尾,而結(jié)束控制語句,,需要使用endif關(guān)鍵字,。
1 2 3 4 5 6 7 | {% if daxin.safe %}
daxin is safe.
{% elif daxin.dead %}
daxin is dead
{% else %}
daxin is okay
{% endif %}
|
jinja2的for循環(huán)
jinja2中的for循環(huán)用于迭代Python的數(shù)據(jù)類型,包括列表,,元組和字典,。在jinja2中不存在while循環(huán)。
迭代列表
1 2 3 4 5 | <ul>
{% for user in users %}
<li>{{ user.username|title }}</li>
{% endfor %}
</ul>
|
迭代字典
1 2 3 4 5 6 | <dl>
{% for key, value in my_dict.iteritems() %}
<dt>{{ key }}</dt>
<dd>{{ value}}</dd>
{% endfor %}
</dl>
|
當(dāng)然也可以加入else語句,,在循環(huán)正確執(zhí)行完畢后,,執(zhí)行
在for循環(huán)中,jinja2還提供了一些特殊的變量,,用以來獲取當(dāng)前的遍歷狀態(tài):
變量 |
描述 |
loop.index |
當(dāng)前迭代的索引(從1開始) |
loop.index0 |
當(dāng)前迭代的索引(從0開始) |
loop.first |
是否是第一次迭代,,返回bool |
loop.last |
是否是最后一次迭代,返回bool |
loop.length |
序列中的項目數(shù)量 |
loop.revindex |
到循環(huán)結(jié)束的次數(shù)(從1開始) |
loop.revindex0 |
到循環(huán)結(jié)束的次數(shù)(從0開始) |
jinja2的宏
宏類似于Python中的函數(shù),,我們在宏中定義行為,還可以進(jìn)行傳遞參數(shù),,就像Python中的函數(shù)一樣一樣兒的,。
在宏中定義一個宏的關(guān)鍵字是macro,,后面跟其 宏的名稱和參數(shù)等
1 2 3 4 5 | {% macro input(name,age=18) %} # 參數(shù)age的默認(rèn)值為18
<input type = 'text' name= "{{ name }}" value= "{{ age }}" >
{% endmacro %}
|
調(diào)用方法也和Python的類似
1 2 | <p>{{ input( 'daxin' ) }} </p>
<p>{{ input( 'daxin' ,age=20) }} </p>
|
jinja2的繼承和Super函數(shù)
jinja2中最強大的部分就是模板繼承。模板繼承允許我們創(chuàng)建一個基本(骨架)文件,,其他文件從該骨架文件繼承,然后針對自己需要的地方進(jìn)行修改。
jinja2的骨架文件中,,利用block關(guān)鍵字表示其包涵的內(nèi)容可以進(jìn)行修改,。
以下面的骨架文件base.html為例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <! 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 %}
< script >This is javascript code </ script >
{% endblock %}
</ div >
</ body >
</ html >
|
這里定義了四處 block,即:head,,title,,content,footer,。那怎么進(jìn)行繼承和變量替換呢,?注意看下面的文件
1 2 3 4 5 6 7 8 9 10 11 12 | { % extend "base.html" % } # 繼承base.html文件
{ % block title % } Dachenzi { % endblock % } # 定制title部分的內(nèi)容
{ % block head % }
{{ super () }} # 用于獲取原有的信息
<style type = 'text/css' >
.important { color: #FFFFFF }
< / style>
{ % endblock % }
# 其他不修改的原封不同的繼承
|
PS: super()函數(shù) 表示獲取block塊中定義的原來的內(nèi)容。
利用jinja2進(jìn)行渲染
jinja2模塊中有一個名為Enviroment的類,,這個類的實例用于存儲配置和全局對象,,然后從文件系統(tǒng)或其他位置中加載模板。
基本使用方法
大多數(shù)應(yīng)用都在初始化的時候撞見一個Environment對象,,并用它加載模板,。Environment支持兩種加載方式:
-
- PackageLoader:包加載器
- FileSystemLoader:文件系統(tǒng)加載器
PackageLoader
使用包加載器來加載文檔的最簡單的方式如下:
1 2 3 4 5 | from jinja2 import PackageLoader,Environment
env = Environment(loader = PackageLoader( 'python_project' , 'templates' )) # 創(chuàng)建一個包加載器對象
template = env.get_template( 'bast.html' ) # 獲取一個模板文件
template.render(name = 'daxin' ,age = 18 ) # 渲染
|
其中:
-
-
- PackageLoader()的兩個參數(shù)為:python包的名稱,以及模板目錄名稱,。
- get_template():獲取模板目錄下的某個具體文件,。
- render():接受變量,對模板進(jìn)行渲染
FileSystemLoader
文件系統(tǒng)加載器,,不需要模板文件存在某個Python包下,,可以直接訪問系統(tǒng)中的文件。
|