flask-wtforms
wtforms主要實現(xiàn)的是表單驗證
預備知識:
當我們實例化一個類的時候我們首先要看其有沒有metaclass如果有創(chuàng)建類的時候首先執(zhí)行metaclass中__init__方法
當我們實例化類的時候先執(zhí)行metaclass中的__call__方法,再執(zhí)行類的__new__方法,最后才執(zhí)行__init__方法
了解源碼:
先貼一個例子吧, 這樣好切入:
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)建了一個表單類,然后我們就可以慢慢開始說了。
代碼一行行開始執(zhí)行當代碼執(zhí)行到
我聲明這個類的時候,我創(chuàng)建了一個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這個返回的實際上是一個由FormMeta為metaclass創(chuàng)建的BaseForm類。所以創(chuàng)建類的時候走FormMeta的__init__方法。在類中定義了兩個屬性_unbound_field和_wtforms_meta。
接著我們看下面,我定義了兩個屬性,分別是兩個類的實例化。老樣子看看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)因為我們在實例化的時候沒有‘_form’,'_name'屬性所以返回的是一個UnboundField對象,主要作用內(nèi)部有一個
UnboundField.creation_counter可以進行計數(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放到一個列表中,然后對其進行排序,付給cls._unbound_fields。cls._wtforms_meta等于一個類。
Form。__init__主要對cls._unbound_fields列表內(nèi)的對象進行實例化然後付給self._fileds[name] = object
最后對其進行循環(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] 加分二叉树
- 下一篇: ubuntu18安装mysql遇到的ro