文章目錄
- 📦 過程詳解(路由 <-> HTML 模板)
- 🧠 數據是怎么傳過去的?
- 多變量示例
- ? Jinja2 支持條件判斷、循環、模板繼承:
- ? 安全性
- 🔒 Flask 默認也會對變量進行 HTML 轉義:
- 📍 {{ chart | safe }}
- 在 pyecharts 中怎么用?
- 📦模板繼承
- 🧱 文件結構示例
- base.html(母板模板)
- index.html(子模板)
- login.html(子模板)
- 📦過濾器
- 📦宏和模板包含
- 📦 Flask-Login 登錄系統
- 1、安裝 Flask-Login:
- 2、初始化 LoginManager
- 3、用戶模型實現:
- 4、登錄與登出視圖示例:
- 5、當前登錄的用戶
- 含義解釋
- 其他常用方法
Flask 使用 Jinja2 模板引擎來處理模板渲染。模板渲染允許你將動態內容插入到 HTML 頁面中,使得應用能夠生成動態的網頁內容。
- 創建模板:將 HTML 文件放在 templates 文件夾中,使用 Jinja2 占位符。
- 渲染模板:使用 render_template 函數在視圖函數中渲染模板。
- 模板繼承:創建基礎模板,允許其他模板繼承和擴展。
- 控制結構:使用條件語句和循環在模板中控制邏輯。
- 過濾器:使用過濾器格式化變量數據。
- 宏和模板包含:創建和使用宏以及模板包含,提高模板的復用性。
- 安全性:Jinja2 默認對模板變量進行自動轉義以防止 XSS 攻擊。
- 模板上下文:將數據傳遞給模板,并在模板中使用這些數據。
📦 過程詳解(路由 <-> HTML 模板)
瀏覽器請求:GET /hello↓
Flask 匹配 @app.route('/hello') → 調用 hello() 函數↓
hello() 中使用 render_template() 渲染 hello.html↓
將 name="張三" 傳入模板引擎 Jinja2↓
Jinja2 渲染出 HTML: <h1>你好, 張三!</h1>↓
Flask 把 HTML 打包成 Response 對象返回瀏覽器↓
瀏覽器顯示頁面
🧠 數據是怎么傳過去的?
render_template("模板名.html", 變量名1=值1, 變量名2=值2, ...)
模板中用 {{ 變量名 }} 就能訪問到。
多變量示例
@app.route('/dashboard')
def dashboard():stats = {"pv": 1000, "uv": 300}return render_template('dashboard.html', stats=stats, username="admin")
templates/dashboard.html
<h2>歡迎, {{ username }}</h2>
<p>頁面瀏覽量:{{ stats.pv }}</p>
<p>獨立訪客數:{{ stats.uv }}</p>
? Jinja2 支持條件判斷、循環、模板繼承:
{% if user %}<p>歡迎 {{ user }}!</p>
{% else %}<p>請先登錄</p>
{% endif %}
{% if user %}
:檢查 user 變量是否存在,如果存在,則顯示歡迎消息,否則顯示登錄提示。
循環語句:
<ul>
{% for item in items %}<li>{{ item }}</li>
{% endfor %}
</ul>
{% for item in items %}
:遍歷 items 列表,并為每個項生成一個 <li>
元素。
? 安全性
自動轉義:Jinja2 默認會對模板中的變量進行自動轉義,防止 XSS 攻擊。
{{ user_input }}
:用戶輸入的內容會被自動轉義,以避免惡意腳本的注入。
🔒 Flask 默認也會對變量進行 HTML 轉義:
比如
chart = "<script>alert('Hi')</script>"
在模版中寫
{{ chart }}
瀏覽器會看到:
<script>alert('Hi')</script>
因為 Flask 模板會自動進行 HTML 安全轉義。
📍 {{ chart | safe }}
{{ chart | safe }} 是 Flask 模板中一個非常常見的寫法,特別用于像 pyecharts、plotly 等圖表庫,把圖表插入 HTML 頁面的關鍵語句。
{{ chart | safe }} 意思是把 chart 的內容作為 HTML 原樣輸出(不再自動轉義)
在 pyecharts 中怎么用?
pyecharts 生成的圖表是一個 HTML
from pyecharts.charts import Bar
from pyecharts import options as optsbar = (Bar().add_xaxis(["A", "B", "C"]).add_yaxis("銷量", [10, 20, 30])
)
chart = bar.render_embed()
在 Flask 中渲染:
return render_template("chart.html", chart=chart)
模板中這樣寫:
<div>{{ chart | safe }}
</div>
這樣圖表就會在頁面中正常顯示!
請不要對用戶輸入的數據使用 | safe,除非你已經對內容做過嚴格校驗,否則可能產生 XSS 攻擊漏洞。
📦模板繼承
模板繼承允許你創建一個基礎模板,然后在其他模板中繼承和擴展這個基礎模板,避免重復的 HTML 代碼。
創建基礎模板:在 templates 文件夾中創建一個基礎模板 base.html。
templates/base.html 示例:
<!DOCTYPE html>
<html>
<head><title>{% block title %}My Website{% endblock %}</title>
</head>
<body><header><h1>My Website</h1></header><main>{% block content %}{% endblock %}</main><footer><p>Footer content</p></footer>
</body>
</html>
{% block title %}
{% endblock %}
和 {% block content %}
{% endblock %}
是定義的可替換區域。
創建子模板:在 templates 文件夾中創建一個子模板 index.html,繼承 base.html。
templates/index.html 文件代碼:
{% extends "base.html" %}{% block title %}Home Page{% endblock %}{% block content %}
<h2>Welcome to the Home Page!</h2>
<p>Content goes here.</p>
{% endblock %}
{% extends "base.html" %}
:繼承基礎模板。
{% block title %}
和 {% block content %}
:重寫基礎模板中的塊內容。
🧱 文件結構示例
templates/
├── base.html ← 通用母版模板
├── index.html ← 首頁(繼承 base)
└── login.html ← 登錄頁(繼承 base)
base.html(母板模板)
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>{% block title %}默認標題{% endblock %}</title><link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body><header><h1>我的網站</h1><nav><a href="{{ url_for('index') }}">首頁</a> |<a href="{{ url_for('login') }}">登錄</a></nav></header><main>{% block content %}{% endblock %}</main><footer><p>版權所有 ? 2025</p></footer>
</body>
</html>
index.html(子模板)
{% extends "base.html" %}{% block title %}首頁{% endblock %}{% block content %}
<h2>歡迎訪問首頁</h2>
<p>這里是首頁內容</p>
{% endblock %}
login.html(子模板)
{% extends "base.html" %}{% block title %}登錄{% endblock %}{% block content %}
<h2>登錄頁面</h2>
<form method="post">用戶名: <input name="username"><br>密碼: <input name="password" type="password"><br><button type="submit">登錄</button>
</form>
{% endblock %}
📦過濾器
過濾器用于在模板中格式化和處理變量數據。
<p>{{ name|capitalize }}</p>
<p>{{ price|round(2) }}</p>
{{ name|capitalize }}
:將 name 變量的值首字母大寫。
{{ price|round(2) }}
:將 price 變量的值四舍五入到小數點后兩位。
📦宏和模板包含
宏是可重用的模板片段。模板包含允許你在一個模板中插入另一個模板的內容。
創建宏
templates/macros.html 代碼文件:
實例
{% macro render_item(item) %}<div><h3>{{ item.title }}</h3><p>{{ item.description }}</p></div>
{% endmacro %}
使用宏:
templates/index.html 文件代碼:
實例
{% from "macros.html" import render_item %}<h1>Items</h1>
{% for item in items %}{{ render_item(item) }}
{% endfor %}
{% from "macros.html" import render_item %}
:導入宏。
{{ render_item(item) }}
:調用宏來渲染每個 item。
📦 Flask-Login 登錄系統
1、安裝 Flask-Login:
pip install flask-login
2、初始化 LoginManager
from flask_login import LoginManagerlogin_manager = LoginManager()
login_manager.init_app(app)@login_manager.user_loader
def load_user(user_id):return User.query.get(user_id)
3、用戶模型實現:
from flask_login import UserMixinclass User(db.Model, UserMixin):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(64), unique=True, nullable=False)# 其他字段...
UserMixin
提供 is_authenticated、is_active、get_id() 等屬性
將 UserMixin
添加到你的用戶模型中后,它會自動為你提供實現 Flask-Login 所要求的接口。
4、登錄與登出視圖示例:
from flask_login import login_user, logout_user@app.route('/login', methods=['GET', 'POST'])
def login():user = User.query.filter_by(username="admin").first()login_user(user) # 登錄return redirect(url_for('index'))@app.route('/logout')
def logout():logout_user()return redirect(url_for('index'))
5、當前登錄的用戶
from flask_login import current_user
<body>{% if current_user.is_authenticated %}<p>歡迎,{{ current_user.username }}!</p><a href="{{ url_for('logout') }}">登出</a>{% else %}<p>您尚未登錄。</p><a href="{{ url_for('login') }}">登錄</a>{% endif %}
</body>
含義解釋
{% if current_user.is_authenticated %}
:在使用 Flask-Login 時,current_user 是 Flask 提供的一個全局代理對象,代表當前登錄的用戶。
current_user.is_authenticated
是一個布爾值:
- True:用戶已登錄
- False:用戶未登錄(匿名)
其他常用方法
代碼 | 說明 |
---|---|
current_user.is_authenticated | 判斷當前用戶是否登錄 |
current_user.username | 訪問當前登錄用戶屬性 |
UserMixin | 提供用戶模型默認認證屬性 |