在開發 Flask Web 應用時,模板引擎是將業務邏輯與視覺呈現分離的關鍵工具。本文將帶你從零開始掌握 Flask 中 Jinja2 模板的核心用法,涵蓋變量渲染、流程控制、循環輸出以及模板繼承等進階技巧。
繼續沿用前一章建立的微博應用結構:
microblog ├── flask/ # 虛擬環境 ├── app/ │ ├── static/ # 靜態資源 │ ├── templates/ # 模板目錄 │ ├── __init__.py │ └── views.py ├── tmp/ └── run.py
確保環境已正確安裝且應用能正常運行,我們將在現有基礎上持續擴展功能。
直接在視圖函數中拼接 HTML 字符串雖然可行,但隨著頁面複雜度增加,維護難度會指數級上升。以首頁歡迎用戶為例:
from app import app
@app.route('/')
@app.route('/index')
def index():
user = {'nickname': 'Miguel'} # 假數據
return '''
<html>
<head><title>Home Page</title></head>
<body><h1>Hello, ''' + user['nickname'] + '''</h1></body>
</html>'''
這種「意大利麵條式代碼」混淆了邏輯與表現,不利於團隊協作與長期維護。模板系統正是為了解決此問題而生——業務邏輯由 Python 處理,頁面結構交給設計師優化。
建立 app/templates/index.html:
<html>
<head><title>{{title}} - microblog</title></head>
<body><h1>Hello, {{user.nickname}}!</h1></body>
</html>
雙大括號 {{ ... }} 是 Jinja2 的變量占位符。對應的視圖函數:
from flask import render_template
from app import app
@app.route('/')
@app.route('/index')
def index():
user = {'nickname': 'Miguel'}
return render_template("index.html", title='Home', user=user)
render_template 內部調用 Jinja2 引擎,將變量替換進模板並返回渲染後的 HTML。
模板支援 {% if ... %} 語句,讓頁面更智能:
<html>
<head>
{% if title %}
<title>{{title}} - microblog</title>
{% else %}
<title>Welcome to microblog</title>
{% endif %}
</head>
<body><h1>Hello, {{user.nickname}}!</h1></body>
</html>
若視圖函數未傳遞 title,頁面將自動顯示預設標題。
模擬用戶動態數據:
def index():
user = {'nickname': 'Miguel'}
posts = [
{'author': {'nickname': 'John'}, 'body': 'Beautiful day in Portland!'},
{'author': {'nickname': 'Susan'}, 'body': 'The Avengers movie was so cool!'}
]
return render_template("index.html", title='Home', user=user, posts=posts)
模板中使用 {% for ... %} 遍歷:
<body>
<h1>Hi, {{user.nickname}}!</h1>
{% for post in posts %}
<p>{{post.author.nickname}} says: <b>{{post.body}}</b></p>
{% endfor %}
</body>
無論列表長短,模板都能自動適配渲染。
當多個頁面共享導航欄、頁腳等結構時,繼承機制大幅減少維護成本。
base.html<html>
<head>
{% if title %}
<title>{{title}} - microblog</title>
{% else %}
<title>microblog</title>
{% endif %}
</head>
<body>
<div>Microblog: <a href="/index">Home</a></div>
<hr>
{% block content %}{% endblock %}
</body>
</html>
{% block content %} 定義可被子模板覆寫的區塊。
index.html{% extends "base.html" %}
{% block content %}
<h1>Hi, {{user.nickname}}!</h1>
{% for post in posts %}
<div><p>{{post.author.nickname}} says: <b>{{post.body}}</b></p></div>
{% endfor %}
{% endblock %}
{% extends "base.html" %} 聲明繼承關係,Jinja2 會自動合併兩模板同名 block。新增頁面時同樣繼承基礎模板,保持風格一致。
本教程涵蓋了 Flask 模板開發的核心知識點:
render_template 分離邏輯與視圖{{ var }} 實現動態內容{% if %} 與循環 {% for %} 控制流程{% extends %} + {% block %} 復用佈局掌握這些技巧,即可構建結構清晰、易於維護的 Flask 應用。下一章將介紹 Web 表單處理,進一步完善用戶交互功能。