如果定义为验证字段,WTForms如何知道使用validate_ <field name =“”>?

时间:2015-07-28 21:04:17

标签: python flask wtforms

当我使用WTForms定义表单时,我可以向子类添加validate_<field name>方法,WTForms知道使用它来验证命名字段。我发现这很有趣,因为方法的名称取决于字段类属性的名称。它如何解决这个问题?

class UploadForm(Form):
    image = FileField("image file")
    submit = SubmitField("Submit")

    def validate_image(self,field):
        if field.data.filename[-4:].lower() != ".jpg":
            raise ValidationError("nope not allowed")

2 个答案:

答案 0 :(得分:3)

WTForms在调用它时检查类(调用类创建一个实例:form = Form())并记录字段及其名称。然后在验证期间,它会查看实例是否有方法validate_<field_name>

FormMeta.__call__内,它使用dir函数列出在类对象上定义的名称并记录字段。

for name in dir(cls):  # look at the names on the class
    if not name.startswith('_'):  # ignore names with leading _
        unbound_field = getattr(cls, name)  # get the value
        if hasattr(unbound_field, '_formfield'):  # make sure it's a field
            fields.append((name, unbound_field))  # record it

Form.validate内,它使用getattr函数尝试为其记录的每个字段获取名称validate_<field name>的值。

for name in self._fields:  # go through recorded field names
    # get method with name validate_<field name> or None
    inline = getattr(self.__class__, 'validate_%s' % name, None)
    if inline is not None:  # if there is such a method record it
        extra[name] = [inline]

答案 1 :(得分:1)

所有Python类型的所有成员实际上都是哈希表(dict s),并且所有类型信息都在运行时生成。所以你可以从代码中检查任何Python类。

作为一个快速互动的例子:

>>> class Foo(object):
...   my_attribute = 'Something'
... 
>>> dir(Foo)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'my_attribute']
>>> Foo.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'Foo' objects>, '__module__': '__main__', 'my_attribute': 'Something', '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None})
>>> [x for x in Foo.__dict__ if not x.startswith('__')]
['my_attribute']
>>>