python Jinja2模板

python Jinja2模板

模板在Python的web開發中應用廣泛,能夠有效的將業務邏輯和頁面邏輯分離。
模板包含的是一個響應文本的文件,包含用佔位變量表示的動態部分,其具體值只在請求的上下文中才能知道。使用真實的值替換變量,再返回最終得到的響應字符串,這一過程稱爲渲染。簡單來說,渲染就是使用真實的值替換變量,再返回最終得到的響應字符串。

Jinja2語法入門

Jinja2是Flask作者開發的一個模板系統。Flask是一個使用Python編寫的輕量級Web應用框架。安裝Flask,Jinja2也會隨之安裝,也可以單獨安裝Jinja2

pip install flask
or 
pip install jinja2

Jinja2模板引擎之所以廣泛使用,是因爲它具有以下優點:

  1. Jinja2更加靈活,提供了控制結構、表達式和繼承等
  2. Jinja2提供了僅有的控制結構,不允許在模板中編寫太多的業務邏輯,避免了工程師亂用行爲。
  3. Jinja2模板的可讀性很好

1 語法塊
jinja2可以應用於任何基於文本的格式,如HTML、XML。Jinja2使用大括號的方式表示Jinja2的語法。
在Jinja2中,存在三種語法:
控制結構:{% %}
變量取值:{{ }}
註釋:{# #}

for循環:

{% for user in users %}
{% endfor%}

if循環:

{% if users %}
	<ul>
	{% for user in users %}
		<li>{{ user.username }}</li>
	{% endfor%}
	</ul>
{% endif %}

2 變量
Jinja2模板中使用{{}}語法表示一個變量,是一種特殊的佔位符,告訴模板引擎這個位置的值在渲染模板時獲取。Jinja2識別所有的Python數據類型,甚至是一些複雜的類型,如列表、字典、對象等。

<p>A value from a dictionary: {{ mydict['key']}}</p>
<p>A value from an object's method: {{myobject.somemethod()}}</p>

3 Jinja2中的過濾器
變量可以通過過濾器進行修改,過濾器可以理解爲是Jinja2裏面的內置函數和字符串處理函數。例如,存在一個名爲lower的過濾器,作用與字符串對象的lower方法一模一樣。
常用的Jinja2過濾器:
字符串操作

過濾器名 說明
safe 渲染時不轉義
capitalize 把值的首字母轉換成大寫,其他字母轉換成小寫
lower 把值轉換成小寫形式
upper 把值轉換成大寫形式
reverse 字符串反轉
title 把值中每個單詞的首字母都轉換成大寫
trim 把值的首尾空格去掉
striptags 渲染之前把值中所有的HTML標籤都刪掉
join 拼接多個值爲字符串
replace 替換字符串的值
round 默認對值進行四捨五入
int 把值轉換成整型
format 格式化輸出
truncate 字符串截斷

列表操作

過濾器 說明
first 取第一個元素
last 取最後一個元素
length 獲取列表長度
sum 列表求和
sort 列表排序

過濾器與變量用管道(|)分割,多個過濾器可以鏈式調用,前一個過濾器的輸出會作爲後一個過濾器的輸入。

{{ "hello world" | replace("hello","goodbye")}}
   -> goodbye world

{{ 42.55 | round | int  }}
	-> 43

4 Jinja2的控制結構
Jinja2中if語句類似於Python中的if語句,需要使用endif語句作爲條件判斷的結束.

{% if a>2 %}
	a大於2
{% elif 1<a<=2%}
	a大於1小於2
{% else %}
	a小於1
{% endif %}

5 Jinja2的for循環
Jinja2中的for語句可用於迭代Python的數據類型,包括列表、元組和字典。
迭代列表:

<ul>
	{% for user in users %}
		<li>{{ user.username }}</li>
	{% endfor %}
</ul>

遍歷字典:
dl 標籤定義了定義列表(definition list)。
dl 標籤用於結合 dt(定義列表中的項目)和 dd(描述列表中的項目)

<dl>
	{% for key,value in d.iteritems() %}
		<dt>{{ key }}</dt>
		<dd>{{ value }}</dd>
	{% endfor %}
</dl>

除了基本的for循環使用以外,Jinja2還提供了一些特殊的變量,不用定義可以直接使用這些變量。
for循環中的特殊變量

變量 描述
loop.index 當前循環迭代的次數(從1開始)
loop.index() 當前循環迭代的次數(從0開始)
loop.revindex 到循環結束的次數(從1開始)
loop.revindex() 到循環結束的次數(從0開始)
loop.first 如果是第一次迭代爲True,否則爲False
loop.last 如果是最後一次迭代,爲True,否則爲False
loop.length 序列中的項目數
loop.cycle 在一串序列間取值的輔助函數

示例如下:保存聯繫人信息,字典的key是聯繫人的名字,字典的value是聯繫人的電話。第一列是序號

{% for key,value in data.iteritems() %}
	<tr class="info">
		<td>{{ loop.index }}</td>
		<td>{{ key }}</td>
		<td>{{ value }}</td>
	</tr>
{% endfor%}

6 Jinja2的宏
宏類似於編程語言中的函數,用於將行爲抽象成可重複調用的代碼塊。與函數一樣,宏分爲定義和調用。
聲明宏如下:
使用macro關鍵字定義一個宏,input是宏的名稱,有三個參數,分別是name,type和value。使用endmacro結束宏的定義。

{% macro input(name,type='text',value='') %}
	<input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

宏的調用如下,與函數調用類似:

<p>{{ input('username',value='user') }}</p>
<p>{{ input('password','password') }}</p>
<p>{{ input('submit','submit','Submit') }}</p>

7 Jinja2的繼承和Super函數
Jinja2中最強大的部分就是模板繼承。模板繼承允許構建一個包含站點共同元素的基本模板骨架,並定義子模板可以覆蓋的塊。
使用{% block name %}的方式定義三個塊,這些塊可以在子模板中進行替換或調用。
父模板:base.html

<!DOCTYPE html>
<html lang="en">
<head>
	{% block head %}
	<link rel="stylesheet" href="style.css" />
		<title>{% block title %}{% endblock %}-Web基礎模板</title>
	{% endblock %}
</head>
<body>
<div id="content">
	{% block content %}{% endblock %}
</div>
</body>

子模板:index.html
使用{% extends ”base.html" %}繼承base.html,繼承以後,base.html中的所有內容都會在index.html中展現。在index.html中,重新定義了title和content這兩個塊的內容

{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
	{{ super() }}
	<style type="text/css">
	.important { color: #336699; }
	</style>
{% endblock %}

{% block content %}
	<h1>Index</h1>
	<p class="important"> 個人博客 </p>
{ % endblock %}

8.Jinja2的其他運算
Jinja2可以對變量進行算數操作、比較操作、邏輯操作。

算數運算 ± */ // % **
比較運算 == != > >= < <=
邏輯運算 not and or

加載模板

想要在模板中使用Jinja2,只需要使用Flask包下的render_template函數訪問模板即可。
Jinja2模塊中有一個名爲Environment的類,這個類的實例用於存儲配置和全局對象,然後從文件系統或其他位置加載模板。

方法一:包加載器
創建Environment對象和包加載器,該加載器會在yourapplication這個python包的templates目錄下查找模板。

from jinja2 import Environment,PackageLoader
env = Environment(loader=PackageLoader('yourapplication','templates'))

接下來,只需要以模板的名字爲參數調用Environment.get_template方法即可。該方法返回一個模板,最後使用模板的render方法進行渲染。

template = env.get_template("mytemplate.html")
print(template.render(the='variable',go='here'))

方法二:文件加載器
文件系統加載器可以直接訪問系統中的文件

import os 
from jinja2 import Environment,FileSystemLoader
def render(tpl_path,**kwargs):
	path,filename = os.path.split(tpl_path)
	env = Environment(loader=FileSystemLoader(path or './'))
	template = env.get_template(filename)
	return template.render(**kwargs)

模板渲染示例:

simple.html
使用for循環遍歷一個列表,列表中的每一項是一個字典。字典中包含了文字和鏈接。將使用字典中的數據渲染HTML超鏈接。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ title | trim }}</title>
</head>
<body>
    <p>{{ content }}</p>
    <ul id="navigation">
        {% for item in items %}
            <li><a href="{{item.href}}">{{ item['caption'] }}</a></li>
        {% endfor %}
    </ul>
</body>
</html>

使用flask下的render_template方法渲染模板

from flask import Flask
from flask import render_template

app = Flask(__name__)
app.config["SECRET_KEY"] = "XXXXDWEFS"
@app.route('/simple/')
def test_simple():
    title = "測試jinjia2模板 "
    items = [{'herf':'https://www.baidu.com/','caption':'百度'},{'herf':'test.www.com','caption':'個人博客'}]
    content = "網站跳轉鏈接如下:"
    return render_template('simple.html',title=title,items=items,content=content)

if __name__ == "__main__":
    app.run(debug=True)

在這裏插入圖片描述

繼承功能示例

base.html

<!DOCTYPE html>
<html lang="en">
    <head>
	    {% block head %}
		    <h4>{% block title %}{% endblock %}-Web基礎模板</h4>
	    {% endblock %}
        <h4>Jinjia2模板示例</h4>
    </head>
    <body>
        <div id="content">
	        {% block content %}
            {% endblock %}
        </div>
        <div id="footer">
            {% block footer %}
            {% endblock %}
        </div>
</body>
</html>

index.html

{% extends "base.html" %}

<!-- 標題模塊被重載 -->
{% block title %}Index{% endblock %}

<!-- head模塊被重載,並且使用super繼承了base.html中head的內容 -->
{% block head %}
	{{ super() }}
	<style type="text/css">
	.important { color: #336699; }
	</style>
{% endblock %}

<!-- 覆蓋了content模塊 -->
{% block content %}
	<h1>歡迎訪問</h1>
	<p class="important"> 個人博客 </p>
{% endblock %}
from flask import Flask
from flask import render_template

app = Flask(__name__)
app.config["SECRET_KEY"] = "XXXXDWEFS"

@app.route('/index/')
def index():
    return render_template('index.html')

if __name__ == "__main__":
    app.run(debug=True)

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章