博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自定义Form组件
阅读量:4462 次
发布时间:2019-06-08

本文共 6612 字,大约阅读时间需要 22 分钟。

一、wtforms源码流程

1、实例化流程分析

1 # 源码流程 2     1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中; meta类读取到cls._wtforms_meta中 3     2. 执行构造方法 4          5         a. 循环cls._unbound_fields中的字段,并执行字段的bind方法,然后将返回值添加到 self._fields[name] 中。 6             即: 7                 _fields = { 8                     name: wtforms.fields.core.StringField(), 9                 }10                 11             PS:由于字段中的__new__方法,实例化时:name = simple.StringField(label='用户名'),创建的是UnboundField(cls, *args, **kwargs),当执行完bind之后,才变成执行 wtforms.fields.core.StringField()12         13         b. 循环_fields,为对象设置属性14             for name, field in iteritems(self._fields):15                 # Set all the fields to attributes so that they obscure the class16                 # attributes with the same names.17                 setattr(self, name, field)18         c. 执行process,为字段设置默认值:self.process(formdata, obj, data=data, **kwargs)19             优先级:obj,data,formdata;20             21             再循环执行每个字段的process方法,为每个字段设置值:22             for name, field, in iteritems(self._fields):23                 if obj is not None and hasattr(obj, name):24                     field.process(formdata, getattr(obj, name))25                 elif name in kwargs:26                     field.process(formdata, kwargs[name])27                 else:28                     field.process(formdata)29             30             执行每个字段的process方法,为字段的data和字段的raw_data赋值31             def process(self, formdata, data=unset_value):32                 self.process_errors = []33                 if data is unset_value:34                     try:35                         data = self.default()36                     except TypeError:37                         data = self.default38         39                 self.object_data = data40         41                 try:42                     self.process_data(data)43                 except ValueError as e:44                     self.process_errors.append(e.args[0])45         46                 if formdata:47                     try:48                         if self.name in formdata:49                             self.raw_data = formdata.getlist(self.name)50                         else:51                             self.raw_data = []52                         self.process_formdata(self.raw_data)53                     except ValueError as e:54                         self.process_errors.append(e.args[0])55         56                 try:57                     for filter in self.filters:58                         self.data = filter(self.data)59                 except ValueError as e:60                     self.process_errors.append(e.args[0])61                 62         d. 页面上执行print(form.name) 时,打印标签63             64             因为执行了:65                 字段的 __str__ 方法66                 字符的 __call__ 方法67                 self.meta.render_field(self, kwargs)68                     def render_field(self, field, render_kw):69                         other_kw = getattr(field, 'render_kw', None)70                         if other_kw is not None:71                             render_kw = dict(other_kw, **render_kw)72                         return field.widget(field, **render_kw)73                 执行字段的插件对象的 __call__ 方法,返回标签字符串
View Code

2、验证流程分析

1 a. 执行form的validate方法,获取钩子方法 2             def validate(self): 3                 extra = {} 4                 for name in self._fields: 5                     inline = getattr(self.__class__, 'validate_%s' % name, None) 6                     if inline is not None: 7                         extra[name] = [inline] 8          9                 return super(Form, self).validate(extra)10         b. 循环每一个字段,执行字段的 validate 方法进行校验(参数传递了钩子函数)11             def validate(self, extra_validators=None):12                 self._errors = None13                 success = True14                 for name, field in iteritems(self._fields):15                     if extra_validators is not None and name in extra_validators:16                         extra = extra_validators[name]17                     else:18                         extra = tuple()19                     if not field.validate(self, extra):20                         success = False21                 return success22         c. 每个字段进行验证时候23             字段的pre_validate 【预留的扩展】24             字段的_run_validation_chain,对正则和字段的钩子函数进行校验25             字段的post_validate【预留的扩展】
View Code

二、自定义Form组件

#!usr/bin/env python# -*- coding:utf-8 -*-from flask import Flask,render_template,request,Markupapp = Flask(__name__,template_folder="templates")app.debug = True# ==============通过这几个类就可以显示了-==============#插件class Widget(object):    passclass InputText(Widget):    def __call__(self, *args, **kwargs):        return ""class TextArea(Widget):    def __call__(self, *args, **kwargs):        return Markup("")#Formclass BaseForm(object):    def __init__(self):        #获取当前所有的字段        _fields = {}        for name, field in self.__class__.__dict__.items():            if isinstance(field, Field):  # 筛选出字段是name和emailDe                _fields[name] = field        self._fields = _fields        self.data = {}        # print(_fields)  # {'name': 111, 'email': 222}    def validate(self,request_data):        #先找到所有的字段,在执行每一个字段的validate方法        flag = True        for name, field in self._fields.items():            input_val = request_data.get(name,"") #用户输入的值            result= field.validate(input_val)  #每一个字段自己校验            print("???????????",input_val,result)            if not result:                flag = False            else:                self.data[name] = input_val        return flag#字段class Field(object):    '''所有类的基类'''    def __str__(self):          #python中的静态字段通过类能找到,通过对象也能找到        return Markup(self.widget())  #self就是StringField,selfclass StringField(Field):  #每个字段打印的时候都要去执行__str__,所以选择放在基类里面,自己没有就调用父类的    widget = InputText()    def validate(self,val):        if val:            return Trueclass EmaliField(Field):    widget = TextArea()    reg = ".*@.*"    def validate(self,val):        import re        print(re.match(self.reg,val),"************")        if re.match(self.reg,val):            return True# ===============使用===============class LoginForm(BaseForm):    name = StringField()    email = EmaliField()@app.route('/index', methods=["GET","POST"])def index():    form = LoginForm()    ret = form.validate(request.form)    print("验证成功",ret)    print("验证成功的值",form.data)    # print(form.name)    # print(form.email)    return render_template("index.html",form=form)if __name__ == '__main__':    app.run()

 

转载于:https://www.cnblogs.com/morgana/p/8493261.html

你可能感兴趣的文章
Floyd判圈算法
查看>>
接口,lambda表达式与内部类(二)
查看>>
Phabricator是什么,代码审查工具
查看>>
Java虚拟机类加载机制
查看>>
DirectX:函数可以连接任意两个filter 分类: Direct...
查看>>
Android APP开发入门教程-Button 分类: JAVA ...
查看>>
WustOJ 1575 Gingers and Mints(快速幂 + dfs )
查看>>
js中,for循环里面放ajax,ajax访问不到变量以及每次循环获取不到数据问题总结...
查看>>
算法:求从1到n这n个整数的十进制表示中1出现的次数-- python 实现
查看>>
CSU 1160 把十进制整数转换为十六进制,格式为0x开头,10~15由大写字母A~F表示
查看>>
LintCode 58: Compare Strings
查看>>
[Unity插件]Lua行为树(五):装饰节点Repeater
查看>>
顺序表、链表、栈和队列
查看>>
Linux第二天(Linux常用命令2)
查看>>
MySql知识体系
查看>>
JIRA中的标记语言的语法参考
查看>>
hdu 6318 Swaps and Inversions(归并排序)
查看>>
用css在IE7、8上实现圆角
查看>>
三维绿幕标定与跟踪
查看>>
android ProgressBar自定义半圆形进度条
查看>>