模板系統(tǒng)基礎(chǔ)
Django 中的模板系統(tǒng)是 Django 框架的重要組成部分。無論哪一個(gè) Web 框架都需要提供動(dòng)態(tài)生成 HTML 頁(yè)面的方式,最常用的做法是使用模板。模板包含一些公共的 HTML 部分以及一些特殊的語(yǔ)法,該語(yǔ)法用于描述如何將數(shù)據(jù)動(dòng)態(tài)插入 HTML 網(wǎng)頁(yè)中。
Django 框架后端默認(rèn)支持自生內(nèi)置的一套模板系統(tǒng) DTL (Django Template Language) 和著名的 Jinja2 模板系統(tǒng)。除此之外,還可以從第三方模塊中選擇其他模板系統(tǒng)。往往內(nèi)置的模板系統(tǒng)以及 Jinja2 已經(jīng)足夠應(yīng)對(duì)大多數(shù)場(chǎng)景了。
1. 什么是模板
模板在生活中也是非常常見的,比如我們上學(xué)時(shí)向老師請(qǐng)假,會(huì)有請(qǐng)假條的模板,只需在請(qǐng)假條模板中填寫請(qǐng)假人以及請(qǐng)假原因就可以。HTML 的模板也是如此,只不過我們會(huì)有特殊的語(yǔ)法來完成一個(gè)模板,接下來會(huì)有對(duì)應(yīng)的模板引擎來幫我們將傳入的數(shù)據(jù)和模板中變量進(jìn)行一一對(duì)應(yīng)并最終形成一個(gè)完整的 HTML 文件。例如下面的一個(gè)最簡(jiǎn)單的模板文件:
<html>
<head></head>
<style type="text/css">
</style>
<body>
<h1>{{ title }}</h1>
</body>
</html>
這個(gè)簡(jiǎn)單的模板中,我們只有一個(gè)模板變量 title
,用 {{
和 }}
括起來。模板引擎會(huì)對(duì)這些變量進(jìn)行數(shù)據(jù)替換,比如傳入數(shù)據(jù) {'title':'標(biāo)題1'}
,那么模板引擎就會(huì)將 {{ title }}
直接替換成 標(biāo)題1
字符串。不同的模板引擎支持不同的語(yǔ)法格式。在 Django 中應(yīng)用最為廣泛的模板引擎當(dāng)屬 Jinja2 了,當(dāng)然它也是 Flask 框架默認(rèn)使用的模板系統(tǒng)。
2. Python中的模板庫(kù)
Python 中比較出名的模板庫(kù)有 2 個(gè),分別是 Mako 和 Jinja2。下面分別來說一說這兩個(gè)模板庫(kù)的用法和一些特點(diǎn)。
Mako 是一個(gè)高性能的 Python 模板庫(kù),它的語(yǔ)法和 API 借鑒了很多其他的模板庫(kù),如 Django、Jinja2 等等。它聲稱有比 Jinja2 更快的解析速度以及更多的語(yǔ)法支持。我們來簡(jiǎn)單過一遍 Mako 中模板語(yǔ)法并用一個(gè)案例進(jìn)行測(cè)試:
-
變量寫法:
${variable}
,在花括號(hào)中還可以執(zhí)行一些 Python 的語(yǔ)法,如:${name.upper()}
會(huì)將 name 的值轉(zhuǎn)換成大寫; -
注釋:?jiǎn)涡凶⑨層?
##
,多行注釋用<%doc></%doc>
;## 兩個(gè)#號(hào)表示單行注釋 <%doc> 多行注釋 </%doc>
-
if 條件語(yǔ)句:控制結(jié)構(gòu)的語(yǔ)法都是以
% name
開頭,以% end
結(jié)尾;% if i == 1: ${i} % endif
-
for 循環(huán):for 循環(huán)的語(yǔ)法是以
% for
開頭,以% endfor
結(jié)尾;% for a in [1, 2, 3, 4, 5]: % if a[0] == 1: its one % elif a[0] == 2: two % else: others % endif % endfor
-
Python 代碼塊:Mako 中嵌入 python 代碼塊時(shí),使用標(biāo)簽
<%
和%>
:<% x=1000 y='imooc' z=y.upper() %> ${x} ${y} ${z}
接下來,我們用編寫簡(jiǎn)單的 Python 代碼測(cè)試下前面用的這些模板語(yǔ)法,基于 Mako 模板引擎來將如下的模板文件渲染成完整的內(nèi)容:
## coding=utf-8
<html>
<head></head>
<style type="text/css">
</style>
<body>
<h1>${title}</h1>
## 打印告警信息
% if has_warn == 'warning':
${warn_msg}
% endif
## 打印動(dòng)物列表
<ul>
% for animal in animals:
<li>${animal}</li>
% endfor
</ul>
## 測(cè)試 python 代碼塊
<%
x='imooc'
y=x.upper()
%>
<div>小寫:${x}</div>
<div>大寫:${y}</div>
</body>
</html>
測(cè)試的 Python 代碼如下:
# 先要安裝 mako 模塊: pip install mako
# 代碼文件名為 test_mako.py
from mako.template import Template
from mako.lookup import TemplateLookup
html_path = '/root/spyinx'
lookup = TemplateLookup(
directories=[html_path],
output_encoding='utf-8',
input_encoding='utf-8',
default_filters=['decode.utf8'],
encoding_errors='replace'
)
# 文件的全路徑為/root/spyinx/index.html
tp = lookup.get_template("/index.html")
values = {
'title': '測(cè)試模板轉(zhuǎn)換',
'has_warn': 'warning',
'warn_msg': '這是一條告警信息',
'animals': ['獅子', '老虎', '蛇']
}
print(str(tp.render(**values), encoding="utf-8"))
執(zhí)行的結(jié)果如下:
(env-3.8.1) [root@server spyinx]# ls
index.html test_mako.py
(env-3.8.1) [root@server spyinx]# python test_mako.py
<html>
<head></head>
<style type="text/css">
</style>
<body>
<h1>測(cè)試模板轉(zhuǎn)換</h1>
這是一條告警信息
<ul>
<li>獅子</li>
<li>老虎</li>
<li>蛇</li>
</ul>
<div>小寫:imooc</div>
<div>大寫:IMOOC</div>
</body>
</html>
可以看到這里的模板文本已經(jīng)被 Mako 引擎進(jìn)行了更新,替換了其中的模板變量,去掉了注釋部分,形成了最終的文本。
接下來,我們也簡(jiǎn)單介紹下 Jinja2 模板庫(kù),它的用法和 Mako 幾乎是類似的,只不過支持的模板語(yǔ)法略有不同。我們會(huì)在后面詳細(xì)介紹 Jinja2,這里簡(jiǎn)單介紹一些常用的語(yǔ)法并使用 Python 代碼進(jìn)行測(cè)試。
-
變量寫法:
{{ variable }}
; -
注釋:注釋的語(yǔ)句是
{# 注釋部分 #}
; -
條件語(yǔ)句:條件語(yǔ)句大多使用 if 語(yǔ)句,它也具有單分支,多分支等多種結(jié)構(gòu)。使用時(shí)需要以 endif 關(guān)鍵字結(jié)尾,而且 if 、elif、else 和 endif 都需要用
{%
和%}
包裹;{% if spyinx.age < 18 %} spyinx is a minor {% elif spyinx.age > 50 %} spyinx is an old man {% else %} spyinx is an adult {% endif %}
-
循環(huán)語(yǔ)句:循環(huán)語(yǔ)句大部分使用 for 語(yǔ)句,它的寫法如下,和 mako 十分類似,使用
{%
和%}
包裹循環(huán)語(yǔ)句,還需要{% endfor %}
結(jié)尾。{% for animal in animals %} {{ animal }} {% endfor %}
除了這些之外,還有過濾器、宏、模板的繼承等等各種強(qiáng)大的功能,全方位滿足各種場(chǎng)景。這些會(huì)留到后面詳細(xì)介紹,下面來完成一個(gè)實(shí)驗(yàn),使用 Jinja2 模板庫(kù)完成對(duì)一個(gè) Jinja2 模板文件的轉(zhuǎn)換:
-
準(zhǔn)備好一個(gè)模板文件 index.html.j2,內(nèi)容如下:
<html> <head></head> <style type="text/css"> </style> <body> <h1>{{ title }}</h1> {# 打印告警信息 #} {%- if has_warn == 'warning' -%} {{ warn_msg }} {%- endif -%} {# 打印動(dòng)物列#} <ul> {%- for animal in animals %} <li>{{ animal }}</li> {%- endfor %} </ul> <div>首字母大寫:{{ 'imooc' | capitalize }}</div> <div>大寫:{{ 'imooc' | upper }}</div> </body> </html>
注意:這里使用
{%-
的寫法是為了去掉類似{% if|for|endif|endfor ... %}
這樣的語(yǔ)句產(chǎn)生的空格。 -
準(zhǔn)備好測(cè)試的 python 代碼,如下:
""" 測(cè)試 jinja2 模塊 """ from jinja2 import Environment, FileSystemLoader def render_template(path, file_name, vars): env = Environment(loader=FileSystemLoader('./')) # 加載模板 template = env.get_template(file_name) content = template.render(vars) print(content) if __name__ == '__main__': values = { 'title': '測(cè)試模板轉(zhuǎn)換', 'has_warn': 'warning', 'warn_msg': '這是一條告警信息', 'animals': ['獅子', '老虎', '蛇'] } render_template('./', 'index.html.j2', values)
-
執(zhí)行該 python 代碼,我們可以得到和前面 Mako 模板庫(kù)一樣的結(jié)果:
(env-3.8.1) [root@server spyinx]# python test_jinja2.py <html> <head></head> <style type="text/css"> </style> <body> <h1>測(cè)試模板轉(zhuǎn)換</h1> 這是一條告警信息 <ul> <li>獅子</li> <li>老虎</li> <li>蛇</li> </ul> <div>首字母大寫:Imooc</div> <div>大寫:IMOOC</div> </body> </html>
至此,我們對(duì) Python 中的模板庫(kù)有了初步的認(rèn)識(shí),接下來就來看看 Django 中的模板系統(tǒng),包括如何配置和使用。
3. 小結(jié)
本小節(jié)中,我們講解了 Django 中模板系統(tǒng)的相關(guān)基礎(chǔ)知識(shí),然后簡(jiǎn)單學(xué)習(xí)了 Python 中的 2 個(gè)流行的模板庫(kù) Mako 和 Jinja2 并進(jìn)行了代碼測(cè)試。接下來便是正式開始深入 Django 中的模板系統(tǒng),包括模板語(yǔ)法、過濾器以及自定義過濾器等。