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-z\d$@$!%*?&]{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__方法,对于类的执行顺序
- 元类的__init__方法
- 元类的__call__方法
- 自己类或基类的__new__方法
- 自己类或基类的__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
作者:RichieWang
出处:https://home.cnblogs.com/u/richiewlq/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,
且在文章页面明显位置给出原文连接。
出处:https://home.cnblogs.com/u/richiewlq/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,
且在文章页面明显位置给出原文连接。