flask-wtforms

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)

  

转载于:https://www.cnblogs.com/Stay-J/p/9010780.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值