未实例化前
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)