WTForms DateTimeField 返回 True 与输入无关
WTForms DateTimeField returning True not matter input
我很难理解为什么 WTForms 总是验证我的输入,即使它与文档中规定的默认输入格式不匹配。文档说默认格式是
class wtforms.fields.DateTimeField(default field arguments, format='%Y-%m-%d %H:%M:%S')
但我的代码总是返回 true
from wtforms import Form, validators
from wtforms.fields import DateTimeField
class InputForm(Form):
timestamp = DateTimeField('TimeStamp', validators=[validators.DataRequired()])
form = InputForm(timestamp='lmao')
form.validate()
# True
谁能给我解释一下这种行为?
简而言之,不会检查您传递给字段的值是否可以强制转换为日期时间,因为您提供的验证器仅检查数据是否存在,而不检查类型。
DateTimeField
确实确保可以将值强制转换为日期时间,但前提是该值来自表单。正如您在下面看到的,通过 kwargs (timestamp='lmao'
) 将值传递给表单构造函数并没有通过相同的测试。
查看 DateTimeField
的定义,唯一具有与作为日期时间字段的字段相关的自定义处理的方法是 process_formdata()
方法(也 _value()
但由小部件用来呈现字段):
class DateTimeField(Field):
"""
A text field which stores a `datetime.datetime` matching a format.
"""
widget = widgets.TextInput()
def __init__(
self, label=None, validators=None, format="%Y-%m-%d %H:%M:%S", **kwargs
):
super(DateTimeField, self).__init__(label, validators, **kwargs)
self.format = format
def _value(self):
if self.raw_data:
return " ".join(self.raw_data)
else:
return self.data and self.data.strftime(self.format) or ""
def process_formdata(self, valuelist):
if valuelist:
date_str = " ".join(valuelist)
try:
self.data = datetime.datetime.strptime(date_str, self.format)
except ValueError:
self.data = None
raise ValueError(self.gettext("Not a valid datetime value"))
当您实例化一个 Form
对象时,将调用表单的 process()
方法,该方法调用每个表单字段的 process()
方法并传递 formdata
(在本例中为 None
) 和字段值(如果可以找到)(在本例中为 'lmao'
)。
可以看到,上面的DateTimeField
定义上没有定义process()
方法,所以调用了Field.process()
:
def process(self, formdata, data=unset_value):
"""
Process incoming data, calling process_data, process_formdata as needed,
and run filters.
If `data` is not provided, process_data will be called on the field's
default.
Field subclasses usually won't override this, instead overriding the
process_formdata and process_data methods. Only override this for
special advanced processing, such as when a field encapsulates many
inputs.
"""
self.process_errors = []
if data is unset_value:
try:
data = self.default()
except TypeError:
data = self.default
self.object_data = data
try:
self.process_data(data)
except ValueError as e:
self.process_errors.append(e.args[0])
if formdata is not None:
if self.name in formdata:
self.raw_data = formdata.getlist(self.name)
else:
self.raw_data = []
try:
self.process_formdata(self.raw_data)
except ValueError as e:
self.process_errors.append(e.args[0])
try:
for filter in self.filters:
self.data = filter(self.data)
except ValueError as e:
self.process_errors.append(e.args[0])
该方法中,参数data
为'lmao'
,formdata
为None
。您可以看到对 process_formdata()
的调用受到 if formdata is not None:
条件的保护,因此对 DateTimeField
上定义的字段的自定义处理仅对来自的数据 运行一个表格。
from werkzeug import MultiDict
form = InputForm(formdata=MultiDict([("timestamp", "lmao")]))
print(form.timestamp.raw_data) # ['lmao']
print(form.timestamp.process_errors) # ['Not a valid datetime value']
print(form.validate()) # False
这意味着您要对通过 kwargs 传递给表单字段的值的有效性负责。
我很难理解为什么 WTForms 总是验证我的输入,即使它与文档中规定的默认输入格式不匹配。文档说默认格式是
class wtforms.fields.DateTimeField(default field arguments, format='%Y-%m-%d %H:%M:%S')
但我的代码总是返回 true
from wtforms import Form, validators
from wtforms.fields import DateTimeField
class InputForm(Form):
timestamp = DateTimeField('TimeStamp', validators=[validators.DataRequired()])
form = InputForm(timestamp='lmao')
form.validate()
# True
谁能给我解释一下这种行为?
简而言之,不会检查您传递给字段的值是否可以强制转换为日期时间,因为您提供的验证器仅检查数据是否存在,而不检查类型。
DateTimeField
确实确保可以将值强制转换为日期时间,但前提是该值来自表单。正如您在下面看到的,通过 kwargs (timestamp='lmao'
) 将值传递给表单构造函数并没有通过相同的测试。
查看 DateTimeField
的定义,唯一具有与作为日期时间字段的字段相关的自定义处理的方法是 process_formdata()
方法(也 _value()
但由小部件用来呈现字段):
class DateTimeField(Field):
"""
A text field which stores a `datetime.datetime` matching a format.
"""
widget = widgets.TextInput()
def __init__(
self, label=None, validators=None, format="%Y-%m-%d %H:%M:%S", **kwargs
):
super(DateTimeField, self).__init__(label, validators, **kwargs)
self.format = format
def _value(self):
if self.raw_data:
return " ".join(self.raw_data)
else:
return self.data and self.data.strftime(self.format) or ""
def process_formdata(self, valuelist):
if valuelist:
date_str = " ".join(valuelist)
try:
self.data = datetime.datetime.strptime(date_str, self.format)
except ValueError:
self.data = None
raise ValueError(self.gettext("Not a valid datetime value"))
当您实例化一个 Form
对象时,将调用表单的 process()
方法,该方法调用每个表单字段的 process()
方法并传递 formdata
(在本例中为 None
) 和字段值(如果可以找到)(在本例中为 'lmao'
)。
可以看到,上面的DateTimeField
定义上没有定义process()
方法,所以调用了Field.process()
:
def process(self, formdata, data=unset_value):
"""
Process incoming data, calling process_data, process_formdata as needed,
and run filters.
If `data` is not provided, process_data will be called on the field's
default.
Field subclasses usually won't override this, instead overriding the
process_formdata and process_data methods. Only override this for
special advanced processing, such as when a field encapsulates many
inputs.
"""
self.process_errors = []
if data is unset_value:
try:
data = self.default()
except TypeError:
data = self.default
self.object_data = data
try:
self.process_data(data)
except ValueError as e:
self.process_errors.append(e.args[0])
if formdata is not None:
if self.name in formdata:
self.raw_data = formdata.getlist(self.name)
else:
self.raw_data = []
try:
self.process_formdata(self.raw_data)
except ValueError as e:
self.process_errors.append(e.args[0])
try:
for filter in self.filters:
self.data = filter(self.data)
except ValueError as e:
self.process_errors.append(e.args[0])
该方法中,参数data
为'lmao'
,formdata
为None
。您可以看到对 process_formdata()
的调用受到 if formdata is not None:
条件的保护,因此对 DateTimeField
上定义的字段的自定义处理仅对来自的数据 运行一个表格。
from werkzeug import MultiDict
form = InputForm(formdata=MultiDict([("timestamp", "lmao")]))
print(form.timestamp.raw_data) # ['lmao']
print(form.timestamp.process_errors) # ['Not a valid datetime value']
print(form.validate()) # False
这意味着您要对通过 kwargs 传递给表单字段的值的有效性负责。