zoukankan      html  css  js  c++  java
  • wtforms源码流程

    未实例化前

    1.继承的Form类

    
    
    # Form(FormMeta("NewBase", (BaseForm,), {}))
    # Form(NewBase(BaseForm))

    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() # Meta()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) def __setitem__(self, name, value): raise TypeError('Fields may not be added to Form instances, only classes.') def __delitem__(self, name): del self._fields[name] setattr(self, name, None) def __delattr__(self, name): if name in self._fields: self.__delitem__(name) else: # This is done for idempotency, if we have a name which is a field, # we want to mask it by setting the value to None. unbound_field = getattr(self.__class__, name, None) if unbound_field is not None and hasattr(unbound_field, '_formfield'): setattr(self, name, None) else: super(Form, self).__delattr__(name) def validate(self): """ Validates the form by calling `validate` on each field, passing any extra `Form.validate_<fieldname>` validators to the field validator. """ 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)

    2.Form的继承类

    def with_metaclass(meta, base=object):
        print(FormMeta("NewBase", (BaseForm,), {}))
        return meta("NewBase", (base,), {})

    它的返回值是继承type的一个元类,所以

    class Form(FormMeta("NewBase", (BaseForm,), {}))
    class Form(NewBase(BaseForm))

    3.创建类的同时变质性创建该元类的init方法

    class FormMeta(type):
        def __init__(cls, name, bases, attrs):
            type.__init__(cls, name, bases, attrs)
            cls._unbound_fields = None
            cls._wtforms_meta = None
    成为创建form组件类的静态字段
    # LoginForm._unbound_fields = None
    # LoginForm._wtforms_meta = None
    class LoginForm(Form):
        name = simple.StringField(

    实例化

    1.首先执行的是元类的call方法

    class FormMeta(type):
    def __call__(cls, *args, **kwargs):
    
            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__:
                    print(mro_class)
                    if 'Meta' in mro_class.__dict__:
                        bases.append(mro_class.Meta)
                print(tuple(bases))
                cls._wtforms_meta = type('Meta', tuple(bases), {})
            return type.__call__(cls, *args, **kwargs)

    2.此时cls._wtforms_meta便是一个有type创建的类,

    cls._unbound_fields是类中所有字段的列表

    cls._unbound_fields = fields
    cls._wtforms_meta = type('Meta', tuple(bases), {})

    3.接下来执行的是Form的init方法

    class Form(with_metaclass(FormMeta, BaseForm)):
    def __init__(self, formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs):
    
            meta_obj = self._wtforms_meta()
            # Meta()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)

    把Meta类实例为对象 meta_obj = self._wtforms_meta(),接下来执行父类的init方法,参数分别是form字段列表,meta对象和前缀

    super(Form, self).__init__(self._unbound_fields, meta=meta_obj, prefix=prefix)
    class BaseForm(object):
    
    
        def __init__(self, fields, prefix='', meta=DefaultMeta()):
    
            if prefix and prefix[-1] not in '-_;:/.':
                prefix += '-'
    
            self.meta = meta
            self._prefix = prefix
            self._errors = None
            self._fields = OrderedDict()
    
            if hasattr(fields, 'items'):
                fields = fields.items()
    
            translations = self._get_translations()
            extra_fields = []
            if meta.csrf:
                self._csrf = meta.build_csrf(self)
                extra_fields.extend(self._csrf.setup_form(self))
    
            for name, unbound_field in itertools.chain(fields, extra_fields):
                options = dict(name=name, prefix=prefix, translations=translations)
                field = meta.bind_field(self, unbound_field, options)
                self._fields[name] = field

    。。。。。。

    4.name = simple.StringField() 为LoginForm类的静态字段,该字段是类的一个实例对象,并接受很多参数

    class StringField(Field):
    
        widget = widgets.TextInput()
    
        def process_formdata(self, valuelist):
            if valuelist:
                self.data = valuelist[0]
            else:
                self.data = ''
    
        def _value(self):
            return text_type(self.data) if self.data is not None else ''

    他继承的是一个Field类

    class Field(object):
        """
        Field base class
        """
        errors = tuple()
        process_errors = tuple()
        raw_data = None
        validators = tuple()
        widget = None
        _formfield = True
        _translations = DummyTranslations()
        do_not_call_in_templates = True  # Allow Django 1.4 traversal
    
        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)

    首先执行的便是new方法,返回的是 self = return UnboundField(cls, *args, **kwargs)

    5.执行UnboundField类的静态字段和init方法

    class UnboundField(object):
        _formfield = True
        creation_counter = 0
    
        def __init__(self, field_class, *args, **kwargs):
            UnboundField.creation_counter += 1
            self.field_class = field_class
            self.args = args
            self.kwargs = kwargs
            self.creation_counter = UnboundField.creation_counter

    创建计数每有一个form字段计数加一

    6.回过来执行Field的init方法

    class Field(object):
    def __init__(self, label=None, validators=None, filters=tuple(),
                     description='', id=None, default=None, widget=None,
                     render_kw=None, _form=None, _name=None, _prefix='',
                     _translations=None, _meta=None):
    
            if _translations is not None:
                self._translations = _translations
    
            if _meta is not None:
                self.meta = _meta
            elif _form is not None:
                self.meta = _form.meta
            else:
                raise TypeError("Must provide one of _form or _meta")
    
            self.default = default
            self.description = description
            self.render_kw = render_kw
            self.filters = filters
            self.flags = Flags()
            self.name = _prefix + _name
            self.short_name = _name
            self.type = type(self).__name__
            self.validators = validators or list(self.validators)
    
            self.id = id or self.name
            self.label = Label(self.id, label if label is not None else self.gettext(_name.replace('_', ' ').title()))
    
            if widget is not None:
                self.widget = widget
    
            for v in itertools.chain(self.validators, [self.widget]):
                flags = getattr(v, 'field_flags', ())
                for f in flags:
                    setattr(self.flags, f, True)
  • 相关阅读:
    python 执行sql得到字典格式数据
    python爬虫 url链接编码成gbk2312格式
    windows环境下elasticsearch安装教程(单节点)
    python SQLServer 存储图片
    爬虫的本质是和分布式爬虫的关系
    requests form data 请求 爬虫
    mysql 删除 binlog 日志文件
    查看mysql数据表的大小
    xshell 连接报错 Disconnected from remote host
    centos 7.3 安装 mysqldb 报错 EnvironmentError: mysql_config not found ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
  • 原文地址:https://www.cnblogs.com/ldq1996/p/8259788.html
Copyright © 2011-2022 走看看