一、什麼是Jinja2模板引擎?¶
在Web開發中,我們常常需要將動態數據(比如從數據庫獲取的用戶信息、文章列表)和靜態頁面(HTML)結合起來,生成最終的網頁。模板引擎就是用來解決這個問題的工具——它允許我們在HTML中嵌入代碼邏輯,動態生成內容。
Flask框架默認使用Jinja2作爲模板引擎,它是一個功能強大且語法簡潔的Python模板引擎。Jinja2支持變量、條件判斷、循環、模板繼承等特性,能讓我們更高效地編寫可複用、易維護的模板代碼。
二、Jinja2基礎語法¶
1. 變量與表達式¶
模板中最基礎的操作是顯示變量。使用{{ 變量名 }}語法嵌入變量,變量由視圖函數(Python代碼)傳遞給模板。
示例:
假設在視圖函數中定義了變量username = "小明",在模板中這樣寫:
<p>歡迎,{{ username }}!</p>
渲染後會輸出:歡迎,小明!
變量可以是字符串、數字、列表、字典等,也可以訪問其屬性或索引:
<!-- 字典 -->
<p>{{ user.age }}</p> <!-- user是字典,輸出user的age值 -->
<!-- 列表 -->
<p>{{ users[0] }}</p> <!-- users是列表,輸出第一個元素 -->
2. 控制結構:條件與循環¶
Jinja2支持條件判斷和循環,讓模板能根據不同情況動態渲染內容。
條件判斷(if-else):
{% if is_login %}
<p>歡迎回來!</p>
{% else %}
<p>請先登錄</p>
{% endif %}
循環(for):
遍歷列表或字典時使用{% for %},並通過loop變量獲取循環狀態(如是否爲第一個元素、總長度等):
<ul>
{% for item in todo_list %}
<li>
{{ loop.index }}. {{ item }}
{% if loop.last %} <!-- 判斷是否爲最後一個元素 -->
<small>(這是最後一項)</small>
{% endif %}
</li>
{% endfor %}
</ul>
如果循環的列表爲空,可通過{% else %}顯示默認內容:
{% for item in todo_list %}
<li>{{ item }}</li>
{% else %}
<p>列表爲空</p>
{% endfor %}
3. 模板繼承與包含¶
爲了避免重複代碼,Jinja2提供模板繼承和模板包含功能。
模板繼承(Extend):
- 定義一個父模板(如base.html),包含通用結構(頭部、底部、導航欄)。
- 子模板通過{% extends "base.html" %}繼承父模板,並覆蓋需要修改的部分。
父模板(base.html):
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}默認標題{% endblock %}</title>
</head>
<body>
<header>
{% block header %}<h1>網站頭部</h1>{% endblock %}
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
{% block footer %}<p>網站底部</p>{% endblock %}
</footer>
</body>
</html>
子模板(index.html):
{% extends "base.html" %} <!-- 繼承父模板 -->
{% block title %}首頁{% endblock %} <!-- 覆蓋title塊 -->
{% block content %} <!-- 覆蓋content塊 -->
<p>這是首頁內容</p>
<ul>
<li>項目1</li>
<li>項目2</li>
</ul>
{% endblock %}
模板包含(Include):
將其他模板片段(如頭部、底部)直接插入當前模板,用於複用通用代碼:
<!-- 在子模板中包含header.html -->
{% include "header.html" %}
4. 過濾器:處理變量¶
過濾器(Filter)用於對變量進行加工(如大小寫轉換、截斷文本等),使用|符號連接。
常用過濾器:
- upper/lower:轉大寫/小寫
{{ name|upper }} → 輸出NAME
- capitalize:首字母大寫
{{ name|capitalize }} → 輸出Name
- truncate(n):截斷文本(保留前n個字符)
{{ long_text|truncate(20) }} → 截斷長文本爲前20字符
- safe:禁用HTML轉義(謹慎使用,防止XSS攻擊)
{{ raw_html|safe }} → 直接渲染HTML代碼
示例:
<p>{{ "hello"|upper }}</p> <!-- 輸出HELLO -->
<p>{{ "123"|int + 456 }}</p> <!-- 轉換爲整數後相加 -->
<p>{{ "Flask is great!"|truncate(10) }}</p> <!-- 截斷爲前10字符:Flask is gr -->
三、Flask與Jinja2的結合使用¶
1. 模板文件結構¶
Flask默認從項目根目錄下的templates文件夾加載模板文件。項目結構示例:
myapp/
├── app.py
└── templates/
├── base.html
├── index.html
└── user.html
2. 渲染模板的核心函數¶
視圖函數通過render_template函數渲染模板,並傳遞變量:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
# 準備數據
users = [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 30}
]
return render_template('index.html', users=users) # 傳遞users到模板
if __name__ == '__main__':
app.run(debug=True)
3. 完整示例:用戶列表頁面¶
模板文件(templates/user_list.html):
{% extends "base.html" %} <!-- 繼承base.html -->
{% block content %}
<h1>用戶列表</h1>
<ul>
{% for user in users %} <!-- 遍歷users列表 -->
<li>
{{ loop.index }}. {{ user.name }} ({{ user.age }}歲)
{% if user.age > 28 %}
<span style="color:red;">(已成年)</span>
{% endif %}
</li>
{% else %}
<p>暫無用戶</p>
{% endfor %}
</ul>
{% endblock %}
視圖函數(app.py):
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/users')
def user_list():
# 模擬數據庫查詢結果
user_data = [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 30},
{"name": "Charlie", "age": 22}
]
return render_template('user_list.html', users=user_data) # 傳遞數據到模板
if __name__ == '__main__':
app.run(debug=True)
四、總結與學習建議¶
Jinja2是Flask的核心組件,掌握其語法能極大提升Web開發效率。重點需掌握:
1. 變量與表達式:{{ variable }}
2. 控制結構:if-else、for循環
3. 模板複用:繼承(extends)和包含(include)
4. 過濾器:|符號處理變量
建議通過以下方式實踐:
- 搭建一個簡單的個人博客,使用模板繼承實現導航欄複用
- 練習循環展示文章列表,結合過濾器截斷長文本
- 嘗試使用safe過濾器渲染富文本內容
通過多寫多練,你會逐漸熟悉Jinja2的靈活語法,讓你的Flask應用更優雅、更高效!