闪现消息(Flash Message)是Flask框架提供的一种机制,用于在请求之间存储消息,并在下一个请求中显示这些消息。通常用于显示操作成功、错误提示或其他一次性通知。
首先需要在Flask应用中导入flash模块并设置secret_key:
# app.py
from flask import Flask, render_template, request, redirect, url_for, flash
app = Flask(__name__)
# 必须设置secret_key才能使用闪现消息
app.config['SECRET_KEY'] = 'your-secret-key-here'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
# 模拟验证逻辑
if username == 'admin' and password == 'password':
flash('登录成功!', 'success')
return redirect(url_for('dashboard'))
else:
flash('用户名或密码错误!', 'error')
return redirect(url_for('login'))
return render_template('login.html')
@app.route('/dashboard')
def dashboard():
return render_template('dashboard.html')
if __name__ == '__main__':
app.run(debug=True)
在HTML模板中使用get_flashed_messages()函数获取消息:
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的Flask应用</title>
<!-- 引入Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-4">
{# 显示闪现消息 #}
{% raw %}{% with messages = get_flashed_messages(with_categories=true) %}{% endraw %}
{% raw %}{% if messages %}{% endraw %}
{% raw %}{% for category, message in messages %}{% endraw %}
<div class="alert alert-{% raw %}{{ category }}{% endraw %} alert-dismissible fade show" role="alert">
{% raw %}{{ message }}{% endraw %}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% raw %}{% endfor %}{% endraw %}
{% raw %}{% endif %}{% endraw %}
{% raw %}{% endwith %}{% endraw %}
{% raw %}{% block content %}{% endraw %}
{% raw %}{% endblock %}{% endraw %}
</div>
<!-- 引入Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
<!-- templates/login.html -->
{% raw %}{% extends "base.html" %}{% endraw %}
{% raw %}{% block content %}{% endraw %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3 class="text-center">用户登录</h3>
</div>
<div class="card-body">
<form method="POST" action="">
<div class="mb-3">
<label for="username" class="form-label">用户名</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">密码</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary">登录</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% raw %}{% endblock %}{% endraw %}
Flash函数接受第二个参数作为消息分类,常用的分类有:
| 分类 | 用途 | 示例 |
|---|---|---|
| success | 成功操作提示 | flash('操作成功!', 'success') |
| error | 错误提示 | flash('操作失败!', 'error') |
| warning | 警告提示 | flash('请注意风险!', 'warning') |
| info | 信息提示 | flash('系统已更新', 'info') |
可以创建自定义的消息过滤器来格式化闪现消息:
# app.py - 自定义闪现消息处理
from flask import Flask, render_template, flash
import markdown
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key-here'
def markdown_filter(message):
"""将Markdown格式的消息转换为HTML"""
return markdown.markdown(message)
app.jinja_env.filters['markdown'] = markdown_filter
@app.route('/')
def index():
flash('**重要**:请及时更新您的个人信息!', 'info')
flash('操作完成', 'success')
return render_template('index.html')
<!-- templates/index.html -->
{% raw %}{% extends "base.html" %}{% endraw %}
{% raw %}{% block content %}{% endraw %}
{% raw %}{% with messages = get_flashed_messages(with_categories=true) %}{% endraw %}
{% raw %}{% if messages %}{% endraw %}
{% raw %}{% for category, message in messages %}{% endraw %}
<div class="alert alert-{% raw %}{{ category }}{% endraw %}">
{# 使用自定义的markdown过滤器 #}
{% raw %}{{ message|markdown|safe }}{% endraw %}
</div>
{% raw %}{% endfor %}{% endraw %}
{% raw %}{% endif %}{% endraw %}
{% raw %}{% endwith %}{% endraw %}
{% raw %}{% endblock %}{% endraw %}
使用flash()函数的第二个参数设置消息为安全的HTML:
# 发送包含HTML的消息
from flask import flash, Markup
@app.route('/message')
def show_message():
# 注意:只有在完全信任用户输入时才使用Markup
message = Markup('操作成功!<a href="/details" class="alert-link">查看详情</a>')
flash(message, 'success')
return render_template('message.html')
在使用Markup或safe过滤器时,请确保消息内容来自可信来源,避免XSS攻击。永远不要将用户输入直接作为HTML内容显示。
# 完整的用户注册示例
from flask import Flask, render_template, request, redirect, url_for, flash
from werkzeug.security import generate_password_hash, check_password_hash
import re
app = Flask(__name__)
app.config['SECRET_KEY'] = 'development-key-123'
# 模拟用户数据库
users = {}
def validate_email(email):
"""验证邮箱格式"""
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, email) is not None
def validate_password(password):
"""验证密码强度"""
if len(password) < 8:
return False, "密码至少需要8个字符"
if not re.search(r'[A-Z]', password):
return False, "密码必须包含至少一个大写字母"
if not re.search(r'[a-z]', password):
return False, "密码必须包含至少一个小写字母"
if not re.search(r'\d', password):
return False, "密码必须包含至少一个数字"
return True, "密码强度符合要求"
@app.route('/')
def home():
return render_template('home.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
confirm_password = request.form['confirm_password']
# 验证邮箱格式
if not validate_email(email):
flash('请输入有效的邮箱地址!', 'error')
return redirect(url_for('register'))
# 验证密码
is_valid, msg = validate_password(password)
if not is_valid:
flash(msg, 'error')
return redirect(url_for('register'))
# 确认密码是否一致
if password != confirm_password:
flash('两次输入的密码不一致!', 'error')
return redirect(url_for('register'))
# 检查用户是否已存在
if email in users:
flash('该邮箱已被注册!', 'error')
return redirect(url_for('register'))
# 保存用户
users[email] = {
'password': generate_password_hash(password),
'email': email
}
flash('注册成功!请登录您的账户。', 'success')
return redirect(url_for('login'))
return render_template('register.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
# 验证用户是否存在
if email not in users:
flash('用户不存在!', 'error')
return redirect(url_for('login'))
# 验证密码
if check_password_hash(users[email]['password'], password):
flash('登录成功!欢迎回来。', 'success')
return redirect(url_for('dashboard'))
else:
flash('密码错误!', 'error')
return redirect(url_for('login'))
return render_template('login.html')
@app.route('/dashboard')
def dashboard():
return render_template('dashboard.html', title='控制面板')
if __name__ == '__main__':
app.run(debug=True)
请检查以下几点:
app.config['SECRET_KEY']?flash()函数?get_flashed_messages()?Flask的闪现消息设计为一次性显示。如果需要持久化消息,可以考虑:
或者,可以在模板中使用Bootstrap的alert组件,并添加data-bs-autohide="false"属性:
<div class="alert alert-success alert-dismissible fade show"
role="alert"
data-bs-autohide="false">
消息内容
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
| 特性 | 闪现消息 | Session消息 |
|---|---|---|
| 存储位置 | Flask session | Flask session |
| 生命周期 | 下一个请求后自动清除 | 需要手动清除 |
| 使用场景 | 一次性通知 | 需要持久化的状态 |
| 获取方式 | get_flashed_messages() |
session.get() |