消息闪现(Flash Messages):给用户即时的操作反馈

📂 所属阶段:第二阶段 — 交互与数据(核心篇)
🔗 相关章节:Flask-WTF 插件 · 路由(Routing)艺术


1. 什么是 Flash?

Flash 消息是在下一个请求中显示一次的临时消息,常用于:

  • "登录成功!"
  • "文章已发布。"
  • "操作失败,请重试。"

1.1 Flash vs 普通消息

普通消息:刷新页面后消失
Flash消息:刷新页面后依然显示(只显示一次)

Flask flash → 存入 session → 下次请求读取后自动清除

2. 基础用法

2.1 使用 flash

from flask import flash, redirect, url_for

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        if check_login():
            flash("登录成功!", "success")
            return redirect(url_for("index"))
        else:
            flash("邮箱或密码错误", "danger")
            return redirect(url_for("login"))
    return render_template("login.html")

2.2 闪现消息分类(Bootstrap 风格)

分类Bootstrap 类适用场景
successalert-success成功操作
infoalert-info提示信息
warningalert-warning警告提示
dangeralert-danger错误提示
primaryalert-primary一般提示
flash("文章已保存!", "success")
flash("请先登录", "warning")
flash("操作失败:网络错误", "danger")
flash("新功能上线了!", "info")

3. 在模板中显示 Flash

3.1 在基础模板中显示

<!-- templates/base.html -->
<body>
    <!-- 在导航栏下方添加 Flash 消息区域 -->
    {% with messages = get_flashed_messages(with_categories=true) %}
        {% if messages %}
            <div class="flash-container" style="position: fixed; top: 70px; right: 20px; z-index: 9999;">
                {% for category, message in messages %}
                    <div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
                        {{ message }}
                        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="关闭"></button>
                    </div>
                {% endfor %}
            </div>
        {% endif %}
    {% endwith %}

    <!-- 其余内容 -->
    {% block content %}{% endblock %}
</body>

3.2 带图标的 Flash

{% with messages = get_flashed_messages(with_categories=true) %}
    {% if messages %}
        <div class="container mt-3">
        {% for category, message in messages %}
            <div class="alert alert-{{ category }} alert-dismissible" role="alert">
                <div class="d-flex align-items-center">
                    {% if category == "success" %}
                        <span style="font-size:1.2em;">✅</span>
                    {% elif category == "danger" %}
                        <span style="font-size:1.2em;">❌</span>
                    {% elif category == "warning" %}
                        <span style="font-size:1.2em;">⚠️</span>
                    {% else %}
                        <span style="font-size:1.2em;">ℹ️</span>
                    {% endif %}
                    <span class="ms-2">{{ message }}</span>
                </div>
                <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
            </div>
        {% endfor %}
        </div>
    {% endif %}
{% endwith %}

3.3 带自动消失的 Flash

<!-- 在 base.html 的 scripts 块中添加 -->
{% block scripts %}
{{ super() }}
<script>
    // Flash 消息 3 秒后自动消失
    document.addEventListener("DOMContentLoaded", function() {
        const alerts = document.querySelectorAll(".alert");
        alerts.forEach(function(alert) {
            setTimeout(function() {
                alert.classList.remove("show");
                setTimeout(function() {
                    alert.remove();
                }, 300);
            }, 3000);  // 3 秒
        });
    });
</script>
{% endblock %}

4. Flash 与表单结合

4.1 表单验证失败的 Flash

@auth_bp.route("/register", methods=["GET", "POST"])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        # 注册成功
        flash("注册成功!请登录。", "success")
        return redirect(url_for("auth.login"))
    else:
        # 表单验证失败
        for field, errors in form.errors.items():
            for error in errors:
                flash(f"{form[field].label.text}: {error}", "danger")
    return render_template("auth/register.html", form=form)

4.2 批量 Flash

# 同时显示多个消息
messages = [
    ("评论已删除", "success"),
    ("你的积分 -5", "info"),
]
for msg, category in messages:
    flash(msg, category)

5. Flash 消息进阶

5.1 闪现带额外数据的消息

# 闪现带链接的消息
flash("你的评论已被删除。申诉?", "warning")
<!-- 模板中解析 -->
{% with messages = get_flashed_messages(with_categories=true) %}
    {% for category, message in messages %}
        <div class="alert alert-{{ category }}">
            {{ message }}
        </div>
    {% endfor %}
{% endwith %}

5.2 带类名的 Flash

# 使用 category 参数指定 Bootstrap 样式类
flash("操作成功!", "success")

# 或者不带分类(默认显示)
flash("一条普通消息")
# → 在模板中用 get_flashed_messages() 获取

6. 小结

# Flash 速查

# 后端
from flask import flash
flash("消息内容", "success|info|warning|danger")

# 模板
{% with messages = get_flashed_messages(with_categories=true) %}
    {% if messages %}
        {% for category, message in messages %}
            <div class="alert alert-{{ category }}">{{ message }}</div>
        {% endfor %}
    {% endif %}
{% endwith %}

💡 使用场景:Flash 最适合操作反馈(提交表单后)、权限提示(未登录)、成功/失败提示。不适合传递重要数据(刷新后就没了)。


🔗 扩展阅读