1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| @app.route('/form') def login(): login_form = LoginForm() 1.先看自己有没有__call__然后一直找到寻源类,metaclass,调用metaclass的__call__方法(这里是FormMeta的__call__) def __call__(cls, *args, **kwargs): if cls._unbound_fields is None: fields = [] for name in dir(cls): if not name.startswith('_'): # 获取unboundfield(1,StringField, 参数) unbound_field = getattr(cls, name) if hasattr(unbound_field, '_formfield'): fields.append((name, unbound_field)) # 按照定义顺序排序 fields.sort(key=lambda x: (x[1].creation_counter, x[0])) cls._unbound_fields = fields 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) 1.获取定义的Field按照计数器排序绑定进unbound_field 2.调用mro继承算法,继承顺序,按照mro顺序找寻每个父类对象的Meta加入bases,(拿到所有的功能),然后生成一个继承所有meta的类并把它赋值给form的 _wtforms_meta class Form(with_metaclass(FormMeta, BaseForm)): Meta = DefaultMeta 3.执行type.__call__( cls, *args, **kwargs)真的call方法 这时loginform中: { ‘__module’: ‘__main__’, ‘name’:<UnboundField>(StringField…..), ‘pwd’: <UnboundField>(PasswordField…..), ‘__doc__’: None, ‘unbound_fields’: [(‘username’,<UnboundField StringField>), (‘pwd’, …….Field)], ‘_wtforms_meta’: class.Meta, }
2.然后执行自己的__new__方法(或继承父类的) 发现父类并没有写__new__,继承的object的。不用找了
3.再执行自己的__init__方法(或继承) 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) 1.实例化_wtforms_meta meta_obj = self._wtforms_meta() meta的功能之一csrf验证隐藏标签,django自带csrf但flask没有,wtform可以提供(生成csrf input框) meta_obj = self._wtforms_meta() if meta is not None and isinstance(meta, dict): meta_obj.update_values(meta) 如果设置了meta参数,比如loginForm(meta={})会帮助更新到wtforms_meta. 2.传入meta和field列表执行父类的构造方法 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._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 1.生成csrf的隐藏field作为extra_field 2.遍历大的field可迭代对象 3.把每个field对象实例化(调用field的bind) def bind(self, form, name, prefix='', translations=None, **kwargs): kw = dict( self.kwargs, _form=form, _prefix=prefix, _name=name, _translations=translations, **kwargs ) return self.field_class(*self.args, **kw)
4.这时候对象有了_name和_field,开始走自己真的__new__(之前是走Unbound的) class Field(object): 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)
|