You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何共享layout.html的登录页无Flash消息,注册页却正常?

Flash消息仅在注册页显示,登录页不显示的原因及解决方法

问题描述

我尝试让Flash消息同时在登录页和注册页显示,两个页面均通过{% extends "layout.html" %}继承同一布局文件,但Flash消息在registration.html上显示正常,在login.html中完全不显示。

登录路由代码

@app.route("/login", methods=["GET", "POST"])
def login():
    """Log user in"""

    # Forget any user_id
    session.clear()

    # User submitted form
    if request.method == "POST":

        # Ensure username was submitted
        if not request.form.get("username"):
            flash('Must provide username', 'error')
            return redirect("/login")


        # Ensure password was submitted
        elif not request.form.get("password"):
            flash('Must provide password', 'error')
            return redirect("/login")

        # Query database for username
        rows = db.execute("SELECT * FROM users WHERE username = ?", request.form.get("username"))

        # Ensure username exists and password is correct
        if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
            flash('Invalid username and/or password', 'error')
            return redirect("/login")

        # Remember which user has logged in
        session["user_id"] = rows[0]["id"]

        # Redirect user to home page
        return redirect("/")

    return render_template("login.html", messages=get_flashed_messages())

注册路由代码

@app.route("/register", methods=["GET", "POST"])
def register():
    """Register user"""
    if request.method == "POST":

        if not request.form.get("username"):
            flash('Invalid Username.', 'error')
            return redirect("/register")


        elif not request.form.get("password"):
            flash('Invalid Password.', 'error')
            return redirect("/register")

        if request.form.get("password") != request.form.get("confirmation"):
            flash('Passwords do not match', 'error')
            return redirect("/register")

        rows = db.execute("SELECT * FROM users WHERE username = ?", request.form.get("username"))
        if len(rows) == 1:
            flash('Username already exists', 'error')
            return redirect("/register")

        username = request.form.get("username")
        hash = generate_password_hash(request.form.get("password"), method='pbkdf2:sha256', salt_length=8)

        db.execute("INSERT INTO users (username,hash) VALUES(?,?)", username, hash)
        return redirect("/login")

    return render_template("register.html", messages=get_flashed_messages())

布局文件layout.html代码

{% block content %}
<div class="text-center">
    {% for message in get_flashed_messages() %}
        <div class="alert alert-dark text-center" role="alert">
            {{ message }}
        </div>
    {% endfor %}
    {% block page_content %}{% endblock %}
</div>
{% endblock %}

问题原因

核心问题出在登录路由的session.clear()调用位置:

  • 登录函数开头的session.clear()会在每次访问/login页面时执行(包括POST验证失败后重定向的GET请求),而Flash消息存储在session中,这会直接清空刚刚存入的Flash消息,导致后续get_flashed_messages()无法获取内容。
  • 注册路由中没有全局的session.clear()调用,Flash消息能保留到重定向后的GET请求中,因此可以正常显示。

另外,两个路由中render_template传入的messages参数是多余的,因为布局文件直接调用get_flashed_messages()而非使用该变量,但这不是登录页消息不显示的直接原因。

解决方法

将session.clear()移到POST请求的处理逻辑内部,仅在用户提交登录表单时清空session,避免影响重定向后的Flash消息:

修改后的登录路由代码:

@app.route("/login", methods=["GET", "POST"])
def login():
    """Log user in"""

    # User submitted form
    if request.method == "POST":
        # 仅在处理登录请求时清空session
        session.clear()

        # Ensure username was submitted
        if not request.form.get("username"):
            flash('Must provide username', 'error')
            return redirect("/login")


        # Ensure password was submitted
        elif not request.form.get("password"):
            flash('Must provide password', 'error')
            return redirect("/login")

        # Query database for username
        rows = db.execute("SELECT * FROM users WHERE username = ?", request.form.get("username"))

        # Ensure username exists and password is correct
        if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
            flash('Invalid username and/or password', 'error')
            return redirect("/login")

        # Remember which user has logged in
        session["user_id"] = rows[0]["id"]

        # Redirect user to home page
        return redirect("/")

    return render_template("login.html")

同时可以移除render_template中多余的messages参数,因为布局文件并未使用该变量。

内容的提问来源于stack exchange,提问作者lozlf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:05:04