flask-wtforms
wtforms主要實(shí)現(xiàn)的是表單驗(yàn)證
預(yù)備知識:
當(dāng)我們實(shí)例化一個(gè)類的時(shí)候我們首先要看其有沒有metaclass如果有創(chuàng)建類的時(shí)候首先執(zhí)行metaclass中__init__方法
當(dāng)我們實(shí)例化類的時(shí)候先執(zhí)行metaclass中的__call__方法,再執(zhí)行類的__new__方法,最后才執(zhí)行__init__方法
了解源碼:
先貼一個(gè)例子吧, 這樣好切入:
from wtforms import Form from wtforms.fields import simple from wtforms import validators from wtforms import widgetsclass 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'})
在上面我創(chuàng)建了一個(gè)表單類,然后我們就可以慢慢開始說了。
代碼一行行開始執(zhí)行當(dāng)代碼執(zhí)行到
我聲明這個(gè)類的時(shí)候,我創(chuàng)建了一個(gè)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 = Nonecls._wtforms_meta = None....
可以看到Form繼承了with_metaclass這個(gè)返回的實(shí)際上是一個(gè)由FormMeta為metaclass創(chuàng)建的BaseForm類。所以創(chuàng)建類的時(shí)候走FormMeta的__init__方法。在類中定義了兩個(gè)屬性_unbound_field和_wtforms_meta。
接著我們看下面,我定義了兩個(gè)屬性,分別是兩個(gè)類的實(shí)例化。老樣子看看meta_class和其中的__init__
看到?jīng)]有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)因?yàn)槲覀冊趯?shí)例化的時(shí)候沒有‘_form’,'_name'屬性所以返回的是一個(gè)UnboundField對象,主要作用內(nèi)部有一個(gè)
UnboundField.creation_counter可以進(jìn)行計(jì)數(shù)我們在看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 inheritancehierarchy."""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放到一個(gè)列表中,然后對其進(jìn)行排序,付給cls._unbound_fields。cls._wtforms_meta等于一個(gè)類。
Form。__init__主要對cls._unbound_fields列表內(nèi)的對象進(jìn)行實(shí)例化然後付給self._fileds[name] = object
最后對其進(jìn)行循環(huán)使用setattr設(shè)置到類中。非常精髓
class Form(with_metaclass(FormMeta, BaseForm)):Meta = DefaultMetadef __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)
轉(zhuǎn)載于:https://www.cnblogs.com/Stay-J/p/9010780.html
總結(jié)
以上是生活随笔為你收集整理的flask-wtforms的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [洛谷P1040] 加分二叉树
- 下一篇: Modbus RTU 通信应用案例