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)

 

posted @ 2018-01-10 17:24  TAMAYURA  阅读(304)  评论(0编辑  收藏  举报