未实例化前

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)

wtforms源码流程的更多相关文章

  1. Flask之wtforms源码分析

    一.wtforms源码流程 1.实例化流程分析 # 源码流程 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: meta类读取到cls._ ...

  2. Flask 源码流程,上下文管理

    源码流程 创建对象 from flask import Flask """ 1 实例化对象 app """ app = Flask(__na ...

  3. ES6.3.2 index操作源码流程

    ES 6.3.2 index 操作源码流程 client 发送请求 TransportBulkAction#doExecute(Task,BulkRequest,listener) 解析请求,是否要自 ...

  4. Eureka服务端源码流程梳理

    一.简述 spring cloud三步走,一导包,二依赖,三配置为我们简化了太多东西,以至于很多东西知其然不知其所以然,了解底层实现之后对于一些问题我们也可以快速的定位问题所在. spring clo ...

  5. django-admin的源码流程

    一.admin的源码流程 首先可以确定的是:路由关系一定对应一个视图函数 a.当点击运行的时候,会先找到每一个app中的admin.py文件,并执行 b.执行urls.py admin.site是什么 ...

  6. Django session 源码流程

    流程 Django session源码流程 首先执行的是SessionMiddleware的init方法 import_module(settings.SESSION_ENGINE) 导入了一个 dj ...

  7. rest_framework解析器组件源码流程

    rest_framework解析器组件源码流程 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数 ...

  8. 【转】ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解

    原文地址:http://blog.csdn.net/a396901990/article/details/36475213 简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量—— ...

  9. Django Rest Framework框架源码流程

    在详细说django-rest-framework源码流程之前,先要知道什么是RESTFUL.REST API . RESTFUL是所有Web应用都应该遵守的架构设计指导原则. REST是Repres ...

随机推荐

  1. freeRTOS中文实用教程6--错误排查

    1.前言 本章主要是为刚接触FreeRTOS 的用户指出那些新手通常容易遇到的问题.这里把最主要的篇幅放在栈溢出以及栈溢出侦测上 2.printf-stdarg.c 当调用标准C 库函数时,栈空间使用 ...

  2. DMA及cache一致性的学习心得 --dma_alloc_writecombine【转】

    转自:https://www.cnblogs.com/hoys/archive/2012/02/17/2355914.html 来源:http://xmxohy.blog.163.com/blog/s ...

  3. linux 查看cpu的使用百分比

    先安装 sudo apt-get install sysstat 然后: mpstat -u 2 5

  4. MySQL日志——Undo | Redo【转】

    本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...

  5. ES系列十七、logback+ELK日志搭建

    一.ELK应用场景 在复杂的企业应用服务群中,记录日志方式多种多样,并且不易归档以及提供日志监控的机制.无论是开发人员还是运维人员都无法准确的定位服务.服务器上面出现的种种问题,也没有高效搜索日志内容 ...

  6. 【转】Source Insight中文注释为乱码的解决办法

    我网上查了一堆解决办法,但是都是2017年以前的,并且都是针对于source insight 3.5及以下版本的解决方案,软件版本都到4.0了,应该有新方法出现. 干货:Source Insight ...

  7. 不同系统与程序修改java.library.path的位置(转)

    原文地址:http://blog.csdn.net/quqibing001/article/details/51201768 Linux环境 系统变量LD_LIBRARY_PATH来添加Java.li ...

  8. 【转】js中的事件委托或是事件代理详解

    起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...

  9. poj3728 倍增法lca 好题!

    lca的好题!网上用st表和离线解的比较多,用树上倍增也是可以做的 不知道错在哪里,等刷完了这个专题再回来看 题解链接https://blog.csdn.net/Sd_Invol/article/de ...

  10. zoj3299 线段树区间更新,坐标建立线段树的方式

    /* 平台和砖块的坐标离散化,边缘坐标转换成单位长度 处理下落信息,sum数组维护区间的砖块数量 把平台按高度从高到低排序,询问平台区间的砖块有多少,询问后将该区域砖块数置0 */ #include& ...