Flask 使用Jinja2模板引擎
Jinja2,由Flask框架的創作者開發,是一款功能豐富的模板引擎,以其完整的Unicode支持、靈活性、高效性和安全性而備受推崇。最初受Django模板引擎啟發,Jinja2為Flask提供了強大的模板支持,后來也成為其他項目的首選。在本文中,我們將深入探討Jinja2的特性、語法以及如何在Flask應用中使用它來構建動態而又美觀的Web頁面。
IF模板
IF語句用于在模板中執行條件判斷,根據不同的條件呈現不同的內容。在模板中,通過{% if condition %} ... {% endif %}的語法結構來定義條件塊。其中,condition是一個表達式或變量,如果該條件為真,模板引擎將執行if塊內的內容,否則將跳過。
IF模板語句支持多種條件判斷,包括比較運算、邏輯運算等。通過合理運用IF語句,可以根據動態數據或用戶輸入,在頁面上展示不同的信息或呈現不同的頁面結構,從而實現更加靈活和個性化的頁面設計。
// ----------------------------------------------
// 前端部分
// ----------------------------------------------
{% if username and username == "admin" %}
<h1>hello {{ username }} welcome</h1>
{% elif username and username == "lyshark" %}
<h1>hello {{ username }}</h1>
{% else %}
<h1>hello lyshark</h1>
{% endif %}
// ----------------------------------------------
// 后端部分
// ----------------------------------------------
@app.route("/", methods=["GET", "POST"])
def index():
return render_template("index.html",username = "admin")
FOR模板
FOR循環模板語句允許在模板中對數據進行迭代操作,便于遍歷集合、列表或字典等數據結構,并在模板中對每個元素執行相同的操作。通過{% for item in iterable %} ... {% endfor %}的語法結構,可以定義一個FOR循環塊。
在FOR循環中,item表示每次迭代中當前的元素,而iterable則是要遍歷的數據集合。循環塊內的代碼將在每次迭代時執行,允許動態生成頁面內容。此外,Jinja2的FOR循環還支持循環索引、循環計數等功能,提供了靈活的迭代控制機制。
FOR模板語句在Web開發中經常用于動態生成頁面元素,特別是在展示多條數據、列表或表格內容時非常實用。通過FOR循環,開發者可以更方便地處理和展示動態數據,提高頁面的靈活性和交互性。
// ----------------------------------------------
// 前端部分
// ----------------------------------------------
<!--輸出列表-->
{% for x in digits %}
<p>輸出列表: {{ x }}</p>
{% endfor %}
<!--輸出字典-->
{% for item in dicts %}
<!--第一個和最后一個元素-->
{% if loop.first %}
<b>第一個元素是: {{ item.name }}</b>
{% elif loop.last %}
<b>最后一個元素是: {{ item.name }}</b>
{% endif %}
<!--下標輸出-->
<b>當前下標(從1開始): {{ loop.index }}</b>
<b>當前下標(從0開始): {{ loop.index0 }}</b>
<!--字典長度-->
<b>數組長度: {{ loop.length }}</b>
<b>迭代計數(從1開始): {{ loop.revindex }}</b>
<b>迭代計數(從0開始): {{ loop.revindex0 }}</b>
<p> 輸出名字: {{ item.name }} 輸出密碼: {{ item.password }}</p>
{% endfor %}
<!--輸出元組-->
{% for href,caption in tuples %}
<p>{{ href }} = {{ caption }}</p>
{% endfor %}
// ----------------------------------------------
// 后端部分
// ----------------------------------------------
@app.route("/", methods=["GET", "POST"])
def index():
return render_template("index.html",
digits=[1,2,3,4,5],
dicts=[
{'name':'John','password':'123123'},
{'name':'Tom', 'password':'123456'},
{'name':'Lisa', 'password':'123123'},
{'name':'Bob', 'password':'123456'}
],
tuples=[
('index.html', 'Index'),
('about.html', 'About'),
('downloads.html', 'Downloads')]
)
FOR模板排序允許在模板中對循環輸出的元素進行排序或分組操作,通過內置的過濾器實現。這提供了更靈活的控制機制,使得模板能夠按照特定的順序展示數據,或者將數據按照某個條件分組呈現。
通過結合FOR循環和排序過濾器,模板可以根據開發者的需求對數據進行動態排列。在模板中,使用類似于{% for item in iterable | sort %} ... {% endfor %}的語法,可以對iterable中的元素進行排序。除了簡單的字母和數字排序外,Jinja2還支持通過自定義函數進行排序,提供了更高度定制的排序功能。
// ----------------------------------------------
// 前端部分
// ----------------------------------------------
<!-- 按指定字段排序,這里設reverse為true使其按降序排 -->
<ul>
{% for item in dicts | sort(attribute='age', reverse=true) %}
<li> 名字: {{ item.name }} 年齡: {{ item.age }}</li>
{% endfor %}
</ul>
<!-- 列表分組,每組是一個子列表,組名就是分組項的值 -->
<ul>
{% for group in dicts|groupby('gender') %}
<li>組名: {{ group.grouper }}
<ul>
{% for user in group.list %}
<li>用戶: {{ user.name }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
<!-- 取字典中的某一項組成列表,再將其連接起來 -->
<p>連接后: {{ dicts | map(attribute='name') | join(', ') }}</p>
<p>連接后: {{ dicts | map(attribute='age') | join(', ') }}</p>
// ----------------------------------------------
// 后端部分
// ----------------------------------------------
@app.route("/", methods=["GET", "POST"])
def index():
return render_template("index.html",
dicts = [
{'name':'Tom','gender':'M','age':20},
{'name':'John','gender':'M','age':18},
{'name':'Mary','gender':'F','age':24},
{'name':'Bob','gender':'M','age':31},
{'name':'Lisa','gender':'F','age':19}]
)
if __name__ == '__main__':
app.run(debug=True)
模板閃現機制
閃現機制是一種在請求之間傳遞信息的有效方式。它允許在一個請求中設置數據,然后在下一個請求中訪問這些數據。主要通過flash()函數實現,使開發者能夠方便地在請求之間傳遞和呈現信息,增強了用戶體驗。
閃現機制通過flash()函數實現,主要分為三種:
-
基本閃現機制: 使用
flash(message, category='message')函數將消息閃現到下一個請求。這個消息可以是字符串,也可以是其他數據類型,而category參數用于指定消息的類別,通常默認為'message'。 -
消息分類: 閃現消息可以根據不同的類別進行分類,以便在前端頁面中有更好的呈現形式。通過設置
category參數,可以將消息劃分為不同的類別,例如'error'、'success'等,以便在模板中有條件地處理這些消息。 -
模板中的處理: 在模板中,可以使用
get_flashed_messages(with_categories=False, category_filter=['error', 'warning'])函數獲取所有閃現的消息。通過with_categories參數可以選擇獲取消息時是否攜帶類別信息,而category_filter參數則可以指定只獲取特定類別的消息。
這三種機制共同構成了Flask框架中靈活且強大的模板閃現系統,使得在Web應用中更便捷地實現消息傳遞和呈現。
1.模板中獲取閃現信息,實現在下次請求時返回內容到前臺。
<!--閃現消息,返回一個列表-->
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% if error %}
<p><strong>失敗消息:</strong> {{ error }}</p>
{% endif %}
<form action="" method=post>
用戶名: <input type=text name=username>
密碼: <input type=password name=password>
<input type=submit value="用戶登錄">
</form>
后端只需要在驗證通過的情況下,直接調用flash()函數實現消息的前臺傳遞。
from flask import Flask, flash, redirect, render_template, request, url_for
app = Flask(__name__, template_folder="./tempate",static_folder="./tempate")
app.secret_key = 'some_secret'
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == "POST":
if request.form['username'] != "lyshark" or request.form['password'] != "1233":
flash("登錄失敗了")
return render_template('index.html',error = "失敗")
else:
flash("恭喜您登錄成功")
return render_template('index.html')
if __name__ == "__main__":
app.run()
2.模板中的分類閃現,在閃現消息是指定一個消息分了i,如果不指定則默認分類為Message消息。
要使用自定義的分類,只要使用flash()函數傳入第二個參數即可。
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul>
{% for category, message in messages %}
<li class="{{ category }}">{{ category }}:{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
后端只需要增加第二個參數來指定需要顯現的分組即可。
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == "POST":
if request.form['username'] != "lyshark" or request.form['password'] != "1233":
flash("登錄失敗了")
return render_template('index.html',error = "失敗")
else:
flash("恭喜您登錄成功","status")
flash("測試賬戶","username")
return render_template('index.html')
if __name__ == "__main__":
app.run()
3.模板中過濾閃現消息,過濾閃現即指在前臺通過category_filter增加過濾條件,來實現對特殊消息的過濾輸出。
<!--閃現消息,增加過濾器-->
{% with messages = get_flashed_messages(category_filter=["username","status"]) %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% if error %}
<p><strong>失敗消息:</strong> {{ error }}</p>
{% endif %}
<form action="" method=post>
用戶名: <input type=text name=username>
密碼: <input type=password name=password>
<input type=submit value="用戶登錄">
</form>
后端也可在閃現消息時指定一個category屬性實現過濾機制。
from flask import Flask, flash, redirect, render_template, request, get_flashed_messages
app = Flask(__name__, template_folder="./tempate",static_folder="./tempate")
app.secret_key = 'some_secret'
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == "POST":
if request.form['username'] != "lyshark" or request.form['password'] != "1233":
flash("登錄失敗了")
return render_template('index.html',error = "失敗")
else:
flash("恭喜您登錄成功","status")
flash("測試新的閃現",category="username") # 輸出到username
flash("測試賬戶","username") # 閃現到username
print('閃現的信息是{}'.format(get_flashed_messages()))
return render_template('index.html')
if __name__ == "__main__":
app.run()
自定義上下文
上下文是一個在請求處理過程中可以訪問的全局對象集合。除了Flask本身提供的默認上下文之外,開發者還可以通過自定義上下文函數來添加額外的全局變量或函數,以便在視圖函數和模板中使用。這就是自定義上下文函數的作用。
關鍵點和優勢:
-
上下文函數的定義: 自定義上下文函數是通過
app.context_processor裝飾器定義的。這個函數會在每次請求處理前被調用,返回的字典中的鍵值對將成為全局變量。 - 全局變量的添加: 開發者可以在自定義上下文函數中添加一些全局變量,這些變量可以在所有視圖函數和模板中直接訪問,無需在每個視圖函數中都進行傳遞。
- 公共函數的注入: 除了變量,還可以在自定義上下文函數中注入一些公共函數。這些函數可以用于處理數據、生成通用的HTML片段等。
- 模板中的使用: 自定義上下文函數中添加的變量可以直接在模板中使用,而無需在每個視圖函數中都傳遞一遍。這簡化了代碼,提高了開發效率。
- 適用于多個視圖: 自定義上下文函數中添加的內容對整個應用程序的多個視圖都是可用的,因此非常適合用于那些需要在整個應用范圍內共享的信息。
通過合理使用自定義上下文函數,可以使Flask應用更加靈活、可維護,并提供一致的全局信息和功能。這種機制有助于將一些通用的操作和數據注入到應用中,提高了代碼的可讀性和可重用性。
下面我們就來先定義一個上下文變量以及上下文函數,將返回字典的屬性指向一個函數即可。
<p>當前APP名字: {{ app_name }}</p>
<p>當前時間戳: {{ local_time }}</p>
<p>當前名字: {{ local_user }}</p>
<p>當前時間: {{ current_time() }}</p>
<p>格式化輸出: {{ current_time("%Y-%m-%d") }}</p>
<p> 傳遞整數調用函數: {{ add_function(34,12) }}</p>
<p> 傳遞數組調用函數: {{ list_function([1,2,3,4,5]) }}</p>
后端代碼編寫部分,需要引入current_app然后在需要定義的函數上增加@app.context_processor裝飾器,返回參數通過字典調用dict(list_function = get)得到結果。
from flask import Flask, render_template
from flask import current_app
import time
app = Flask(__name__)
# 自定義變量
@app.context_processor
def appinfo():
return dict(app_name = current_app.name,
local_time = time.time(),
local_user = "lyshark"
)
# 自定義函數
@app.context_processor
def app_function_gettime():
def get_time(timeFormat="%b %d, %Y - %H:%M:%S"):
return time.strftime(timeFormat)
return dict(current_time = get_time)
# 自定義函數(傳遞整數)
@app.context_processor
def app_function_add():
def get(x=0,y=0):
z = x + y
return z
return dict(add_function = get)
# 自定義函數(傳遞數組)
@app.context_processor
def app_function_list():
def get(x=[]):
sum = 0
for item in x:
sum = sum + item
return sum
return dict(list_function = get)
@app.route("/", methods=["GET", "POST"])
def index():
return render_template("index.html")
if __name__ == '__main__':
app.run(debug=True)
自定義過濾器
自定義過濾器是一種強大的工具,允許開發者在模板中對數據進行各種處理和格式化操作。過濾器其實就是函數,通過使用add_template_filter方法將自定義函數注冊為模板過濾器,從而在模板中調用。
關鍵點和優勢:
-
過濾器的定義: 開發者可以通過定義一個函數,并使用
add_template_filter方法將這個函數注冊為模板過濾器。這個函數將用于對模板中的數據進行處理。 - 數據處理和格式化: 自定義過濾器可以執行各種數據處理和格式化操作,如日期格式化、字符串截斷、數據轉換等。這有助于在模板中減少邏輯處理,保持模板的簡潔性。
- 可重用性: 通過自定義過濾器,開發者可以將常用的數據處理邏輯抽象成函數,提高代碼的可重用性。這些過濾器可以在多個模板和視圖*享使用。
- 模板中的使用: 一旦注冊了自定義過濾器,就可以在模板中使用它。通過在模板中調用過濾器函數,并傳遞相應的參數,可以對模板中的數據進行實時處理。
- 框架集成: Flask提供了簡單而強大的方式來集成自定義過濾器,使得開發者可以輕松地擴展模板引擎的功能,滿足不同場景下的需求。
通過靈活使用自定義過濾器,可以使模板引擎更加強大,滿足更復雜的展示需求。這種機制有助于降低模板中的代碼復雜度,提高開發效率,同時保持模板的可讀性。
過濾器其實是一個函數,函數支持自定義功能,通過flask的add_template_filter將我們的函數加入到過濾器表單中。
<p>輸出雙數: {{ [1,2,3,4,5,6,7,8,9,10] | double_step }}</p>
<p>輸出子列表: {{ [1,2,3,4,5,6,7,8,9,10] | sub_step(1,5) }}</p>
<p>全局函數調用: {{ global_add(10,20,30) }} </p>
后臺增加過濾器有兩種方式,直接在函數上增加@app.template_filter('sub_step')裝飾器實現,或通過add_template_filter將某個函數直接定義為過濾器使用。
from flask import Flask, render_template
from flask import current_app
app = Flask(__name__)
@app.route("/", methods=["GET", "POST"])
def index():
return render_template("index.html")
# 增加過濾器(方式1),輸出列表中的雙數
def double_step_filter(x):
return x[::2]
app.add_template_filter(double_step_filter,"double_step")
# 增加過濾器(方式2)
@app.template_filter('sub_step')
def sub(x, start, end):
return x[start:end]
# 增加全局函數
@app.template_global('global_add')
def function(x,y,z):
return x+y+z
if __name__ == '__main__':
app.run(debug=True)
自定義測試器
自定義測試器是一種用于在模板中進行條件判斷的工具。類似于過濾器,自定義測試器也是通過注冊函數的方式來實現的,但是它們主要用于在模板中執行布爾條件測試。
關鍵點和優勢:
-
測試器的定義: 開發者可以定義一個函數,并使用
@app.template_test()裝飾器將其注冊為模板測試器。這個函數將包含一些布爾條件判斷邏輯。 - 條件判斷: 自定義測試器主要用于在模板中進行條件判斷。通過在模板中調用測試器函數,并傳遞相應的參數,可以獲取布爾值,用于控制模板中的條件分支。
- 可讀性和模塊化: 將常用的布爾條件判斷邏輯抽象成測試器函數,有助于提高模板中的可讀性和模塊化程度。這使得在模板中的條件判斷部分更為清晰和易于維護。
- 模板中的使用: 一旦注冊了自定義測試器,就可以在模板中使用它。通過在模板中調用測試器函數,并傳遞相應的參數,可以獲得布爾值,從而決定模板中的條件分支。
- 框架集成: Flask提供了簡單而強大的方式來集成自定義測試器,使得開發者可以輕松地擴展模板引擎的功能,實現更靈活的條件判斷。
通過合理使用自定義測試器,可以使得模板中的條件判斷更為清晰和靈活。這種機制有助于降低模板中的代碼復雜度,提高開發效率,同時使得模板的邏輯更易于理解和維護。
自定義測試器與過濾器基本一致,區別在于測試器使用@app.template_test()裝飾函數,其他方法與過濾器保持一致。
<!--驗證字符串結尾是否是指定字符-->
{% if name is end_with "me" %}
<h2>"字符串 {{ name }}" 結尾是 "me"</h2>
{% else %}
<h2>"字符串 {{ name }}" 結尾不是 "me"</h2>
{% endif %}
<!--驗證數組中是否有大于10的元素-->
{% if lists is array_of "10" %}
<h2>列表中存在,大于10的數據</h2>
{% endif %}
測試器后端分別定義兩個函數,一個用于判斷字符串結尾是否存在某個字符,另一個則是驗證數組內是否存在大于元素。
from flask import Flask, render_template
app = Flask(__name__)
# 自定義測試器
@app.template_test('end_with')
def end_with(str,suffix):
return str.lower().endswith(suffix.lower())
# 自定義測試器(測試數組內是否有大于某值的)
@app.template_test('array_of')
def array_of(str,suffix):
for item in str:
if item >= int(suffix):
return True
@app.route("/", methods=["GET", "POST"])
def index():
return render_template("index.html",name = "lyshark me", lists = [1,2,3,4,5,6,7,8,56,33])
if __name__ == '__main__':
app.run(debug=True)
總結
以上是生活随笔為你收集整理的Flask 使用Jinja2模板引擎的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 代码质量-开闭原则
- 下一篇: 写代码不用"if"行不行,曾经的反 if