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'formdataNone。您可以看到对 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 传递给表单字段的值的有效性负责。