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

如何为Flask WTForms编辑资料路由预填充表单并正确获取提交数据

问题根因

你的代码错误在于无论GET还是POST请求,都先给表单字段的data属性覆盖了数据库中的旧值:当用户提交POST请求时,Flask-WTF本会自动将请求数据加载到表单的data属性中,但你随后的赋值操作直接把新提交的数据覆盖成了旧的用户版本数据,所以才会出现data一直是初始值、只有raw_data里存了新输入的情况。


修复方案

方案1:调整赋值时机(仅GET请求时填充初始值)

仅在页面初次加载(GET请求)、且表单未提交的场景下给表单赋初始值,POST请求时不做覆盖,让Flask-WTF正常加载请求数据即可:

@app.route("/edit_user", methods=["GET", "POST"])
@login_required
def edit_user_self():
    """Edit user account that is currently logged in."""
    # 获取当前登录用户的最新版本
    user_version = current_user.user_versions[0]
    # 实例化表单,POST请求时会自动加载请求数据
    form = EditUserForm()

    # 仅GET请求(未提交)时填充旧数据
    if request.method == 'GET':
        form.username.data = user_version.username
        form.email.data = user_version.email
        form.addr_housenumber.data = user_version.addr_housenumber
        form.addr_street.data = user_version.addr_street
        form.addr_unit.data = user_version.addr_unit
        form.addr_city.data = user_version.addr_city
        form.addr_state.data = user_version.addr_state
        form.addr_postcode.data = user_version.addr_postcode

    if form.validate_on_submit():
        # 校验通过后这里拿到的form.*.data就是用户提交的新值
        new_user_version = UserVersion(
            user=current_user,
            username = form.username.data,
            password = user_version.password,
            email = form.email.data,
            addr_housenumber = form.addr_housenumber.data,
            addr_street = form.addr_street.data,
            addr_unit = form.addr_unit.data,
            addr_city = form.addr_city.data,
            addr_state = form.addr_state.data,
            addr_postcode = form.addr_postcode.data
        )
        db.session.add(new_user_version)
        db.session.commit()
        flash("Changes saved")
        return redirect("/view_user")
    # 校验失败或GET请求时渲染模板,表单会自动带对应值(初次加载是旧值,校验失败是用户刚输入的值)
    return render_template("edit_user.html", form=form)

方案2:使用obj参数自动填充表单(更优雅)

Flask-WTF实例化表单时支持传入obj参数,会自动将对象的同名属性赋值给表单字段,不需要手动逐个赋值,同样要注意仅GET请求时传入即可:

# 实例化表单时GET请求传obj,POST请求不传,自动加载请求数据
form = EditUserForm(obj=user_version if request.method == 'GET' else None)

如果你的UserVersion对象字段和表单字段完全同名的话,后面手动给每个字段赋值的代码可以全部删掉,非常简洁。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 21:24:01