WTForms:即使数据存在,也可以跳过可选的验证器

WTForms: Optional validator skipping even though data exists

这是提炼代码:

from wtforms import (
    Form,
    StringField,
    validators,
)


class UserForm(Form):
    email = StringField('Email', validators=[
        validators.Optional(),
        validators.Email(),
    ])


form = UserForm(data={'email': ''})
form.validate()
print(form.errors)  # No errors as expected

form = UserForm(data={'email': 'lem'})
form.validate()
print(form.errors)  # This should have an error

form = UserForm(data={'email': 'lem@email.com'})
form.validate()
print(form.errors)  # No errors as expected

输出:

{}
{}
{}

无论字段中是否有数据,似乎让 Optional 都会跳过后续验证。我怀疑这可能与通过数据传递字典有关。我不确定。

删除 validators.Optional 给了我预期的结果:

{'email': ['Invalid email address.']}
{'email': ['Invalid email address.']}
{}

这是一个带有电子邮件验证器的电子邮件字段不相关。即使我改用 validators.Length(min=5) 也存在同样的问题。

问题是由于您使用 data 参数而不是 formdata 来初始化表单。根据文档,formdata 用于在 post 请求之后传递来自最终用户的数据,而 dataobj 用于在初始 get 请求期间提供数据最终用户可以编辑并 post 返回。因此,由 dataobj 提供的数据永远不会被表单验证,因为这是来自应用程序或数据库的已知有效数据。但是,您必须将支持 getlist 方法的 multidict 而不是简单的字典传递给 formdata。为此,您可以使用 werkzeug MultiDict 或 django MultiValueDict。

from werkzeug import MultiDict
from wtforms import Form, StringField, validators

class UserForm(Form):
    email = StringField('Email', validators=[validators.Optional(), validators.Email()]

form = UserForm(formdata=MultiDict({'email': 'lem'}))
form.validate()