zoukankan      html  css  js  c++  java
  • 十四 .Flask wtforms 前戏知识点 和 源码解析

    一 .wtforms 前戏知识点和源码解析

    https://blog.csdn.net/u011884100/article/details/88095304

    https://www.jianshu.com/p/abcd051d45fc

    1. 生成器 和面向对象

    生成器函数 
    
     form对象为什么可以被for循环?
                          :变为可迭代对象。
    
     
    class Foo(object):
    
        # def __iter__(self):
        #     return iter([11,22,33])
    
        def __iter__(self):
            yield 1
            yield 2
            yield 3
    
    obj = Foo()
    
    for item in obj:
        print(item)
    内成员
    class Foo(object): x1 = 123 def func(self): pass print(dir(Foo)) """['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__' , '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'func', 'x1'] """
    __new__方法  - new方法的返回值决定对象到底是什么?
    
    class Bar(object):
        pass
    
    class Foo(object):
        def __new__(cls, *args, **kwargs):
            return "aaaa"
    obj = Foo()
    print(obj) # aaaa
    
    
    
    class Bar(object):
        pass
    class Foo(object):
        def __new__(cls, *args, **kwargs):
            return super(Foo,cls).__new__(cls,*args, **kwargs)
    obj = Foo()
    print(obj) # <__main__.Foo object at 0x000001CCE7048D68>
    
    
    
    
    
    class Bar(object):
        pass
    class Foo(object):
        def __new__(cls, *args, **kwargs):
            # return super(Foo,cls).__new__(cls,*args, **kwargs)
            return Bar()
    obj = Foo()
    print(obj) <__main__.Bar object at 0x0000022BBAFD8978>
    
    
    
    
    
    class Bar(object):
        def __init__(self,cls):
            self.cls = cls
    
    class Foo(object):
    
        def __new__(cls, *args, **kwargs):
            # return super(Foo,cls).__new__(cls,*args, **kwargs)
            return Bar(cls)
    obj = Foo()
    print(obj) # <__main__.Bar object at 0x000001C73DD78DA0>
    类创建的两种方式
    class Foo(object):
        a1 = 123
        def func(self):
            return "AAA"
    obj=Foo()
    
    
    Foo = type("Foo",(object,),{'a1':123,'func':lambda self:666})
    cc=Foo()
    
    
    # 自定义type
    # 注意:metaclass作用是指定当前类由谁来创建。
    class MyType(type):
        pass
    class Foo(object,metaclass=MyType):
        a1 = 123
        def func(self):
            return 666
    
    metaclass
     metaclass
                    - 创建类时,先执行type的__init__。
                    - 类的实例化时,执行type的__call__,__call__方法的的返回值就是实例化的对象__call__内部调用- 类.__new__,创建对象
                                - 类.__init__,对象的初始化
    class MyType(type):
        def __init__(self,*args,**kwargs):
            super(MyType,self).__init__(*args,**kwargs)
    
        def __call__(cls, *args, **kwargs):
            obj = cls.__new__(cls)
    
            cls.__init__(obj,*args, **kwargs)
    
            return obj
    
    class Foo(object,metaclass=MyType):
        a1 = 123
        def __init__(self):
            pass
    
        def __new__(cls, *args, **kwargs):
            return object.__new__(cls)
    
        def func(self):
            return 666
    # Foo是类
    # Foo是MyType的一个对象
    obj = Foo()
    print(obj) # <__main__.Foo object at 0x000002668D98EEB8>


     2. wtforms 源码解析

    实例化流程分析
    
     1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中; meta类读取到cls._wtforms_meta中
        2. 执行构造方法
            
            a. 循环cls._unbound_fields中的字段,并执行字段的bind方法,然后将返回值添加到 self._fields[name] 中。
                即:
                    _fields = {
                        name: wtforms.fields.core.StringField(),
                    }
                    
                PS:由于字段中的__new__方法,实例化时:name = simple.StringField(label='用户名'),创建的是UnboundField(cls, *args, **kwargs),当执行完bind之后,才变成执行 wtforms.fields.core.StringField()
            
            b. 循环_fields,为对象设置属性
                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)
            c. 执行process,为字段设置默认值:self.process(formdata, obj, data=data, **kwargs)
                优先级:obj,data,formdata;
                
                再循环执行每个字段的process方法,为每个字段设置值:
                for name, field, in iteritems(self._fields):
                    if obj is not None and hasattr(obj, name):
                        field.process(formdata, getattr(obj, name))
                    elif name in kwargs:
                        field.process(formdata, kwargs[name])
                    else:
                        field.process(formdata)
                
                执行每个字段的process方法,为字段的data和字段的raw_data赋值
                def process(self, formdata, data=unset_value):
                    self.process_errors = []
                    if data is unset_value:
                        try:
                            data = self.default()
                        except TypeError:
                            data = self.default
            
                    self.object_data = data
            
                    try:
                        self.process_data(data)
                    except ValueError as e:
                        self.process_errors.append(e.args[0])
            
                    if formdata:
                        try:
                            if self.name in formdata:
                                self.raw_data = formdata.getlist(self.name)
                            else:
                                self.raw_data = []
                            self.process_formdata(self.raw_data)
                        except ValueError as e:
                            self.process_errors.append(e.args[0])
            
                    try:
                        for filter in self.filters:
                            self.data = filter(self.data)
                    except ValueError as e:
                        self.process_errors.append(e.args[0])
                    
            d. 页面上执行print(form.name) 时,打印标签
                
                因为执行了:
                    字段的 __str__ 方法
                    字符的 __call__ 方法
                    self.meta.render_field(self, kwargs)
                        def render_field(self, field, render_kw):
                            other_kw = getattr(field, 'render_kw', None)
                            if other_kw is not None:
                                render_kw = dict(other_kw, **render_kw)
                            return field.widget(field, **render_kw)
                    执行字段的插件对象的 __call__ 方法,返回标签字符串
    验证流程分析
    
    a. 执行form的validate方法,获取钩子方法
                def validate(self):
                    extra = {}
                    for name in self._fields:
                        inline = getattr(self.__class__, 'validate_%s' % name, None)
                        if inline is not None:
                            extra[name] = [inline]
            
                    return super(Form, self).validate(extra)
            b. 循环每一个字段,执行字段的 validate 方法进行校验(参数传递了钩子函数)
                def validate(self, extra_validators=None):
                    self._errors = None
                    success = True
                    for name, field in iteritems(self._fields):
                        if extra_validators is not None and name in extra_validators:
                            extra = extra_validators[name]
                        else:
                            extra = tuple()
                        if not field.validate(self, extra):
                            success = False
                    return success
            c. 每个字段进行验证时候
                字段的pre_validate 【预留的扩展】
                字段的_run_validation_chain,对正则和字段的钩子函数进行校验
                字段的post_validate【预留的扩展】
  • 相关阅读:
    delphi快捷键
    Delphi代码规范
    Hibernate通用Dao
    SpringData初探
    Windows下shell神器
    正则语法总结
    nodejs的npm命令无反应的解决方案
    JavaScript中,返回上一个页面时,如何保证上一个页面的不刷新?
    js上传图片
    正则匹配结果取反(正则中的前瞻,负向前瞻与后顾)
  • 原文地址:https://www.cnblogs.com/lovershowtime/p/11753504.html
Copyright © 2011-2022 走看看