flask WTForms源码分析及自定义WTForms

首先我们来创建一个From类

from wtforms.form import Form
from wtforms import StringField
from wtforms.validators import DataRequired
name = simple.StringField( label='用户名', validators=[ validators.DataRequired(message='用户名不能为空.'), validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d') ], widget=widgets.TextInput(), render_kw={'class': 'form-control'} ) # pwd = UnboundField(PasswordField, *args, **kwargs) creation_counter=2 pwd = simple.PasswordField( label='密码', validators=[ validators.DataRequired(message='密码不能为空.'), validators.Length(min=8, message='用户名长度必须大于%(min)d'), validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[$@$!%*?&])[A-Za-zd$@$!%*?&]{8,}", message='密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符') ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} # 定义css样式 ) class Meta: csrf = False # 是否自动创建csrf def validate_pwd(self,*args,**kwargs): ""验证用户密码"" pass @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'GET': return render_template('login.html', form=form) else: form = LoginForm(formdata=request.form) if form.validate(): print('用户提交数据通过格式验证,提交的值为:', form.name.data,form.pwd.data) else: print(form.errors) return render_template('login.html', form=form)

 当代码运行起来之后我们可以看到这样的页面:

当我们看到这个页面的时候,我们是否想过后台到底发生了什么,为我们生成了这样的页面呢。接下来我们从Form模块的导入来分析:

首先从导入的Form,这个类是怎么定义的呢:

class Form(with_metaclass(FormMeta, BaseForm)):
    pass

 一般我们看到的类的继承,都是写一个类,with_metaclass 应该是我们第一次见到,她到底作业什么呢?我们继续查看

def with_metaclass(meta, base=object):
    # 通过meta创建一个类 并继承base,实际上是继承了两个类(meta,base)
    return meta("NewBase", (base,), {})

当我们实例化From或From的派生类的时候就会调用FormMeta的,因为FormMeta继承了type并重写了__call__方法,对于类的执行顺序 

  1.  元类的__init__方法
  2. 元类的__call__方法
  3. 自己类或基类的__new__方法
  4. 自己类或基类的__init__方法

 

所以先执行 FormMeta的init之后执行他的call方法

class FormMeta(type):
    
    def __init__(cls, name, bases, attrs):
        type.__init__(cls, name, bases, attrs)
        cls._unbound_fields = None
        cls._wtforms_meta = None

 

接下来我们来继续分析FromMeta的call方法

 def __call__(cls, *args, **kwargs):
       
        if cls._unbound_fields is None:  # 第一次为None
            fields = []
            for name in dir(cls):            # 获取类中的所有的静态方法和字段
                if not name.startswith('_'):    # 排除非私有方法和字段
                    unbound_field = getattr(cls, name)   #反射获取字段名
                    if hasattr(unbound_field, '_formfield'):   # Filed的静态标识
                        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:  # 第一次为None
            bases = []
            for mro_class in cls.__mro__:   # 或去派生类的Meta类
                if 'Meta' in mro_class.__dict__:
                    bases.append(mro_class.Meta)
            cls._wtforms_meta = type('Meta', tuple(bases), {})
        return type.__call__(cls, *args, **kwargs)

 元类执行完成之后继续执行执行Form或BaseForm(自身或基类)的__new__和__init__方法

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

  

  

  

原文地址:https://www.cnblogs.com/richiewlq/p/8270599.html