validate_on_submit 无法从 WTForms FormField 取回数据
Can not get data back from WTForms FormField on validate_on_submit
user_edit_profile.html:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block mainbody %}
<div class="container">
<div class="col-md-8 col-md-offset-2">
<div class="page-header">
<h3>{{ _('User Edit Profile') }}</h3>
</div>
<div>
{{ wtf.quick_form(form, form_type="horizontal", horizontal_columns=('md', 3, 9)) }}
</div>
</div>
</div>
{% endblock %}
forms.py
from flask_wtf import FlaskForm
from wtforms import Form
class UserBasicInfoForm(Form):
surname = StringField(lazy_gettext("Surname"), validators=[Length(0, 64)])
class UserEditProfileForm(FlaskForm):
basic_information = FormField(UserBasicInfoForm)
submit = SubmitField(lazy_gettext("Submit"), id="user_edit_profile_submit")
user.py
@user.route("/edit-profile", methods=["GET", "POST"])
@login_required
def edit_profile():
form = UserEditProfileForm()
form.basic_information.surname.data = current_user.surname
if form.validate_on_submit():
current_user.surname = form.basic_information.surname.data
print(form.basic_information.surname.data)
current_user.save()
return redirect(url_for("frontend.index"))
return render_template("user_edit_profile.html", form=form)
我没有贴models.py
因为效果很好,我觉得没问题。
现在,print(form.basic_information.surname.data)
反馈 None
,这意味着我无法从 wtf 表单的 surname
字段中输入任何内容。
当我用Charles抓包的时候,发现客户端真的把输入的东西,比如"Smith"发给了服务器。但显然服务器丢失了它。
我还尝试在子表单中使用 FlaskForm
而不是 Form
,同时我使用以下方法将 csrf_enabled
args 覆盖为 False
:
def __init__(self, *args, **kwargs):
kwargs['csrf_enabled'] = False
FlaskForm.__init__(self, *args, **kwargs)
但这并没有帮助。
不知道哪里出了问题,谢谢大家的帮助!
这个问题的起因是order,一开始你的current_user.surname
是None
,你这样写:
form.basic_information.surname.data = current_user.surname
所以你的form.basic_information.surname.data
是None
,同时表单数据form.basic_information.surname.data
被覆盖了
正确的顺序是这样的:
@user.route("/edit-profile", methods=["GET", "POST"])
@login_required
def edit_profile():
form = UserEditProfileForm()
if form.validate_on_submit():
# first!
current_user.surname = form.basic_information.surname.data
print(form.basic_information.surname.data)
current_user.save()
return redirect(url_for("frontend.index"))
# second!
form.basic_information.surname.data = current_user.surname
return render_template("user_edit_profile.html", form=form)
user_edit_profile.html:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block mainbody %}
<div class="container">
<div class="col-md-8 col-md-offset-2">
<div class="page-header">
<h3>{{ _('User Edit Profile') }}</h3>
</div>
<div>
{{ wtf.quick_form(form, form_type="horizontal", horizontal_columns=('md', 3, 9)) }}
</div>
</div>
</div>
{% endblock %}
forms.py
from flask_wtf import FlaskForm
from wtforms import Form
class UserBasicInfoForm(Form):
surname = StringField(lazy_gettext("Surname"), validators=[Length(0, 64)])
class UserEditProfileForm(FlaskForm):
basic_information = FormField(UserBasicInfoForm)
submit = SubmitField(lazy_gettext("Submit"), id="user_edit_profile_submit")
user.py
@user.route("/edit-profile", methods=["GET", "POST"])
@login_required
def edit_profile():
form = UserEditProfileForm()
form.basic_information.surname.data = current_user.surname
if form.validate_on_submit():
current_user.surname = form.basic_information.surname.data
print(form.basic_information.surname.data)
current_user.save()
return redirect(url_for("frontend.index"))
return render_template("user_edit_profile.html", form=form)
我没有贴models.py
因为效果很好,我觉得没问题。
现在,print(form.basic_information.surname.data)
反馈 None
,这意味着我无法从 wtf 表单的 surname
字段中输入任何内容。
当我用Charles抓包的时候,发现客户端真的把输入的东西,比如"Smith"发给了服务器。但显然服务器丢失了它。
我还尝试在子表单中使用 FlaskForm
而不是 Form
,同时我使用以下方法将 csrf_enabled
args 覆盖为 False
:
def __init__(self, *args, **kwargs):
kwargs['csrf_enabled'] = False
FlaskForm.__init__(self, *args, **kwargs)
但这并没有帮助。
不知道哪里出了问题,谢谢大家的帮助!
这个问题的起因是order,一开始你的current_user.surname
是None
,你这样写:
form.basic_information.surname.data = current_user.surname
所以你的form.basic_information.surname.data
是None
,同时表单数据form.basic_information.surname.data
被覆盖了
正确的顺序是这样的:
@user.route("/edit-profile", methods=["GET", "POST"])
@login_required
def edit_profile():
form = UserEditProfileForm()
if form.validate_on_submit():
# first!
current_user.surname = form.basic_information.surname.data
print(form.basic_information.surname.data)
current_user.save()
return redirect(url_for("frontend.index"))
# second!
form.basic_information.surname.data = current_user.surname
return render_template("user_edit_profile.html", form=form)