![](/img/trans.png)
[英]validate_on_submit always returns false using Flask WTForms
[英]Flask WTForms always give false on validate_on_submit()
我使用 wtforms 创建了一个注册表单。 我在其中使用 FormField,这样我就不必再次重复表单的某些元素。 但是每当我单击“提交”按钮时,它总是在调用 validate_on_submit 方法时给我 false。 不明白为什么会这样。
我的form.py
如下:
class ProfileInfoForm(Form):
firstname = TextField('firstname', validators=
[validators.Required("Please enter First name.")])
lastname = TextField('lastname', validators=
[validators.Required("Please enter Last name.")])
email = EmailField('email', validators=
[validators.Required("Please enter your valid email.")])
gender = RadioField('gender', validators=
[validators.Required("Please select gender")],
choices=[('female', 'Female'), ('male', 'Male')])
dob = TextField('dob', validators=
[validators.Required("Please select date of birth.")])
languages = SelectMultipleField('languages', choices=[('', '')],
validators=
[validators.Required("Please select\
atleast one \
language.")])
class RegistrationForm(Form):
profilefield = FormField(ProfileInfoForm)
password = PasswordField('password',
validators=
[validators.Required("Please enter password."),
validators.Length(min=8),
validators.EqualTo('confirm_password',
message='Password and confirm\
password must match')])
confirm_password = PasswordField('confirm_password',
validators=
[validators.Required("Please enter\
confirm password.")])
tnc = BooleanField('tnc', validators=
[validators.Required("Please select Terms and \
Conditions")], default=False)
submit = SubmitField('Create My Account')
Signup
方法如下:
@module.route('/signup', methods=['GET', 'POST'])
@handle_error
def signup():
if hasattr(g, 'user') and g.user:
# TODO: do some operations if needed else keep it blank
return redirect(url_for('index'))
else:
signup_form = RegistrationForm()
# Add choices for the user
signup_form.profilefield.languages.choices = getLanguages()
if signup_form.validate_on_submit():
firstname = signup_form.profilefield.firstname.data
lastname = signup_form.profilefield.lastname.data
email = signup_form.profilefield.email.data
password = signup_form.password.data
# confirm_password = signup_form.confirm_password.data
gender = signup_form.profilefield.gender.data
dob = signup_form.profilefield.dob.data
languages = signup_form.profilefield.languages.data
tnc = signup_form.tnc.data
payload = {'firstname': firstname, 'lastname': lastname,
'email': email, 'password': password, 'gender': gender,
'dob': dob, 'languages': languages,
'tnc': ('1' if tnc else '0')}
try:
buildApiUrl = BuildApiUrl()
response = requests.post(buildApiUrl.getUrl("user", "signup"),
data=payload)
if response.status_code == requests.codes.ok:
data = json.loads(response.text)
if 'status' in data and data['status'] != 200:
flash(data['message'], category="error")
else:
flash(data['message'] +
': Your account is created successfully! ' +
'Please login to your account!',
category="success")
return redirect(url_for('index'))
except requests.exceptions.RequestException:
flash('Internal Server side error occured', category="error")
return redirect(url_for('server_error', e='500'))
return render_template('public/index.html',
signup_form=signup_form, login_form=LoginForm())
HTML 表格出现在此处的要点上
仅供参考:我将所有必填字段与所需的实际数据放在一起。 当我调用 validate_on_submit() 时仍然出错。 我的代码有什么问题?
编辑:getLanguages 是一种从数据库中检索语言并放入 select 列表的方法。 此功能按预期发生,我可以获得语言列表。
编辑 2:在这里实现一件事。 这是由于 FormField 而发生的,因为我通过将 ProfileInfoForm() 的所有字段添加到 RegistrationForm() 方法中进行了测试,并且一切正常,我可以注册。 所以 FormField 或我使用它的方式存在一些问题,但不确定哪里出错了。
发现问题不在于 FormField,而在于我的 ProfileInfoForm()。 它总是返回 false。 还没有理由,但我想我可能必须为此编写自己的验证。 有什么想法吗?
编辑:
在转储时,我得到了以下信息(在这里使用了 pprint):
{'SECRET_KEY': '1e4c35233e50840483467e8d6cfe556c',
'_errors': None,
'_fields': {'csrf_token': <wtforms.ext.csrf.fields.CSRFTokenField object at 0x2207290>,
'dob': <wtforms.fields.simple.TextField object at 0x2207650>,
'email': <flask_wtf.html5.EmailField object at 0x22074d0>,
'firstname': <wtforms.fields.simple.TextField object at 0x2207350>,
'gender': <wtforms.fields.core.RadioField object at 0x2207590>,
'languages': <wtforms.fields.core.SelectMultipleField object at 0x2207710>,
'lastname': <wtforms.fields.simple.TextField object at 0x2207410>},
'_prefix': u'profilefield-',
'csrf_enabled': True,
'csrf_token': <wtforms.ext.csrf.fields.CSRFTokenField object at 0x2207290>,
'dob': <wtforms.fields.simple.TextField object at 0x2207650>,
'email': <flask_wtf.html5.EmailField object at 0x22074d0>,
'firstname': <wtforms.fields.simple.TextField object at 0x2207350>,
'gender': <wtforms.fields.core.RadioField object at 0x2207590>,
'languages': <wtforms.fields.core.SelectMultipleField object at 0x2207710>,
'lastname': <wtforms.fields.simple.TextField object at 0x2207410>}
编辑:
我挖掘了一下,发现错误是由于缺少 csrf 令牌而产生的。 但是我在 html 的表单模板中包含了{{ signup_form.hidden_tag() }}
。我可以看到在检查元素时生成的 html 中的隐藏标签,并且可以看到具有 hash 值的 csrf_token 字段。 那么这里有什么问题呢?
我通过以下功能解决了我的问题:
def __init__(self, *args, **kwargs):
kwargs['csrf_enabled'] = False
super(ProfileInfoForm, self).__init__(*args, **kwargs)
我在ProfileInfoForm()
添加了此功能
问题是FormField
包含csrf_token
字段以及实际表单,即RegistrationForm
也包含csrf_token,因此有两个要验证的csrf_token
,只有一个实际在表单中呈现。 因此,我在ProfileInfoForm
禁用了csrf_token
,因此当FormField呈现它时,它具有csrf_token = False
。
而且RegistrationForm
确实现在csrf_token
启用了csrf_token
因此该表单仍然是安全的。
我的猜测是,这也需要在FormField
完成。
仅供参考:由于我对FormField代码的解释,此解决方案可能是错误的。 因此,如果上述解决方案有误,请纠正我。
我遇到了同样的问题,并且能够解决它。
该问题与以下事实有关:LoginForm具有ID和带有验证程序的用户名,而html表单不需要信息。
<h1>Login</h1>
<form action="" method="POST" name="login">
{{ login_form.csrf_token }}
{{ login_form.hidden_tag() }}
<p>
{{ login_form.email.label }}<br>
{{ login_form.email(size=64) }}<br>
{% for error in login_form.email.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ login_form.password.label }}<br>
{{ login_form.password(size=32) }}<br>
{% for error in login_form.password.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ login_form.remember_me }} Remember Me</p>
{# <input type="submit" value="Sign In">#}
<p>{{ login_form.submit() }}</p>
</form>
class LoginForm(FlaskForm):
***# user_id = StringField('user_id',validators=[DataRequired()])
# user_name = StringField('user_name',validators=[DataRequired(), Length(min=3, max=20)])***
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('remember_me', default=False)
submit = SubmitField('LogIn')
只需使用 jinja 打印 csrf_token,它就会返回 True。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.