如果 WTForms 被定义为验证字段,它如何知道使用 validate_<field name>?
How does WTForms know to use validate_<field name> if it is defined to validate a field?
当我使用 WTForms 定义表单时,我可以将 validate_<field name>
方法添加到 subclass,并且 WTForms 知道使用它来验证命名字段。我觉得这很有趣,因为方法的名称取决于字段 class 属性的名称。它是如何解决这个问题的?
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")
所有 Python 类型的所有成员实际上都是哈希表 (dict
s) 并且所有类型信息都在运行时具体化。因此,您可以从代码中检查任何 Python class。
作为一个快速交互示例:
>>> 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']
>>>
WTForms 在调用时检查 class(调用 class 创建实例:form = Form()
)并记录字段及其名称。然后在验证期间,它会查看实例是否具有方法 validate_<field_name>
.
在 FormMeta.__call__
, it uses the dir
函数中列出在 class 对象上定义的名称并记录字段。
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
it uses the 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]
当我使用 WTForms 定义表单时,我可以将 validate_<field name>
方法添加到 subclass,并且 WTForms 知道使用它来验证命名字段。我觉得这很有趣,因为方法的名称取决于字段 class 属性的名称。它是如何解决这个问题的?
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")
所有 Python 类型的所有成员实际上都是哈希表 (dict
s) 并且所有类型信息都在运行时具体化。因此,您可以从代码中检查任何 Python class。
作为一个快速交互示例:
>>> 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']
>>>
WTForms 在调用时检查 class(调用 class 创建实例:form = Form()
)并记录字段及其名称。然后在验证期间,它会查看实例是否具有方法 validate_<field_name>
.
在 FormMeta.__call__
, it uses the dir
函数中列出在 class 对象上定义的名称并记录字段。
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
it uses the 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]