• 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)
    

      

  • 相关阅读:
    河南省第十二届大学生程序设计竞赛 F: Information Transmission-1(二分图最大匹配)
    hdu1068:Girls and Boys(最大独立集)
    hdu1068:Girls and Boys(最大独立集)
    hdu1281:棋盘游戏(二分图最大匹配)
    hdu1281:棋盘游戏(二分图最大匹配)
    洛谷P1991 :无线通讯网(最小生成树)
    洛谷P1991 :无线通讯网(最小生成树)
    oGitHub 注册
    Lambda应用设计模式 [转载]
    读取excel数据 到 datagrid 出现 找不到可安装的ISAM
  • 原文地址:https://www.cnblogs.com/Stay-J/p/9010780.html
Copyright © 2020-2023  润新知