wtforms主要实现的是表单验证
预备知识:
当我们实例化一个类的时候我们首先要看其有没有metaclass如果有创建类的时候首先执行metaclass中__init__方法
当我们实例化类的时候先执行metaclass中的__call__方法,再执行类的__new__方法,最后才执行__init__方法
了解源码:
先贴一个例子吧, 这样好切入:
from wtforms import Form from wtforms.fields import simple from wtforms import validators from wtforms import widgets class LoginForm(Form): user = simple.StringField( validators=[ validators.DataRequired(message='不能为空') ], widget=widgets.TextInput(), render_kw={'class': 'form-control'} ) pwd = simple.PasswordField( validators=[ validators.DataRequired(message='不能为空') ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} )
在上面我创建了一个表单类,然后我们就可以慢慢开始说了。
代码一行行开始执行当代码执行到
我声明这个类的时候,我创建了一个LoginForm的类:这是看看我继承的Form中是否有metaclass如果有看看有没有__init__方法
class Form(with_metaclass(FormMeta, BaseForm)): 。。。。
class FormMeta(type): def __init__(cls, name, bases, attrs): type.__init__(cls, name, bases, attrs) cls._unbound_fields = None cls._wtforms_meta = None ....
可以看到Form继承了with_metaclass这个返回的实际上是一个由FormMeta为metaclass创建的BaseForm类。所以创建类的时候走FormMeta的__init__方法。在类中定义了两个属性_unbound_field和_wtforms_meta。
接着我们看下面,我定义了两个属性,分别是两个类的实例化。老样子看看meta_class和其中的__init__
看到没有metaclass那一切就变得简单了,我们在看看是否有__new__方法
class Field(object): 。。。 def __new__(cls, *args, **kwargs): if '_form' in kwargs and '_name' in kwargs: return super(Field, cls).__new__(cls) else: return UnboundField(cls, *args, **kwargs)
因为我们在实例化的时候没有‘_form’,'_name'属性所以返回的是一个UnboundField对象,主要作用内部有一个
UnboundField.creation_counter可以进行计数
我们在看FormMeta中的__call__
def __call__(cls, *args, **kwargs): """ Construct a new `Form` instance. Creates the `_unbound_fields` list and the internal `_wtforms_meta` subclass of the class Meta in order to allow a proper inheritance hierarchy. """ if cls._unbound_fields is None: fields = [] for name in dir(cls): if not name.startswith('_'): unbound_field = getattr(cls, name) if hasattr(unbound_field, '_formfield'): fields.append((name, unbound_field)) # We keep the name as the second element of the sort # to ensure a stable sort. fields.sort(key=lambda x: (x[1].creation_counter, x[0])) cls._unbound_fields = fields # Create a subclass of the 'class Meta' using all the ancestors. if cls._wtforms_meta is None: bases = [] for mro_class in cls.__mro__: if 'Meta' in mro_class.__dict__: bases.append(mro_class.Meta) cls._wtforms_meta = type('Meta', tuple(bases), {}) return type.__call__(cls, *args, **kwargs)
主要是把所有unbound_field放到一个列表中,然后对其进行排序,付给cls._unbound_fields。cls._wtforms_meta等于一个类。
Form。__init__主要对cls._unbound_fields列表内的对象进行实例化然後付给self._fileds[name] = object
最后对其进行循环使用setattr设置到类中。非常精髓
class Form(with_metaclass(FormMeta, BaseForm)): Meta = DefaultMeta def __init__(self, formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs): meta_obj = self._wtforms_meta() if meta is not None and isinstance(meta, dict): meta_obj.update_values(meta) super(Form, self).__init__(self._unbound_fields, meta=meta_obj, prefix=prefix) for name, field in iteritems(self._fields): # Set all the fields to attributes so that they obscure the class # attributes with the same names. setattr(self, name, field) self.process(formdata, obj, data=data, **kwargs)