自定义Form组件
一、wtforms源码流程
1、实例化流程分析
- # 源码流程
- 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中; meta类读取到cls._wtforms_meta中
- 2. 执行构造方法
- a. 循环cls._unbound_fields中的字段,并执行字段的bind方法,然后将返回值添加到 self._fields[name] 中。
- 即:
- _fields = {
- name: wtforms.fields.core.StringField(),
- }
- PS:由于字段中的__new__方法,实例化时:name = simple.StringField(label='用户名'),创建的是UnboundField(cls, *args, **kwargs),当执行完bind之后,才变成执行 wtforms.fields.core.StringField()
- b. 循环_fields,为对象设置属性
- 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)
- c. 执行process,为字段设置默认值:self.process(formdata, obj, data=data, **kwargs)
- 优先级:obj,data,formdata;
- 再循环执行每个字段的process方法,为每个字段设置值:
- for name, field, in iteritems(self._fields):
- if obj is not None and hasattr(obj, name):
- field.process(formdata, getattr(obj, name))
- elif name in kwargs:
- field.process(formdata, kwargs[name])
- else:
- field.process(formdata)
- 执行每个字段的process方法,为字段的data和字段的raw_data赋值
- def process(self, formdata, data=unset_value):
- self.process_errors = []
- if data is unset_value:
- try:
- data = self.default()
- except TypeError:
- data = self.default
- self.object_data = data
- try:
- self.process_data(data)
- except ValueError as e:
- self.process_errors.append(e.args[0])
- if formdata:
- try:
- if self.name in formdata:
- self.raw_data = formdata.getlist(self.name)
- else:
- self.raw_data = []
- self.process_formdata(self.raw_data)
- except ValueError as e:
- self.process_errors.append(e.args[0])
- try:
- for filter in self.filters:
- self.data = filter(self.data)
- except ValueError as e:
- self.process_errors.append(e.args[0])
- d. 页面上执行print(form.name) 时,打印标签
- 因为执行了:
- 字段的 __str__ 方法
- 字符的 __call__ 方法
- self.meta.render_field(self, kwargs)
- def render_field(self, field, render_kw):
- other_kw = getattr(field, 'render_kw', None)
- if other_kw is not None:
- render_kw = dict(other_kw, **render_kw)
- return field.widget(field, **render_kw)
- 执行字段的插件对象的 __call__ 方法,返回标签字符串
2、验证流程分析
- a. 执行form的validate方法,获取钩子方法
- def validate(self):
- 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)
- b. 循环每一个字段,执行字段的 validate 方法进行校验(参数传递了钩子函数)
- def validate(self, extra_validators=None):
- self._errors = None
- success = True
- for name, field in iteritems(self._fields):
- if extra_validators is not None and name in extra_validators:
- extra = extra_validators[name]
- else:
- extra = tuple()
- if not field.validate(self, extra):
- success = False
- return success
- c. 每个字段进行验证时候
- 字段的pre_validate 【预留的扩展】
- 字段的_run_validation_chain,对正则和字段的钩子函数进行校验
- 字段的post_validate【预留的扩展】
二、自定义Form组件
- #!usr/bin/env python
- # -*- coding:utf-8 -*-
- from flask import Flask,render_template,request,Markup
- app = Flask(__name__,template_folder="templates")
- app.debug = True
- # ==============通过这几个类就可以显示了-==============
- #插件
- class Widget(object):
- pass
- class InputText(Widget):
- def __call__(self, *args, **kwargs):
- return "<input type='text' name='name'>"
- class TextArea(Widget):
- def __call__(self, *args, **kwargs):
- return Markup("<textarea name='email'></textarea>")
- #Form
- class 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,self
- class StringField(Field): #每个字段打印的时候都要去执行__str__,所以选择放在基类里面,自己没有就调用父类的
- widget = InputText()
- def validate(self,val):
- if val:
- return True
- class 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()
自定义Form组件的更多相关文章
- 仿照wtform自定义Form组件
仿照wtforms自定义Form组件 1.wtforms 点击查看源码分析及使用方法 2.自定义Form组件 #!usr/bin/env python # -*- coding:utf-8 -*- f ...
- Tronado自定义Form组件
Tronado自定义Form组件 一.获取类里面的静态属性以及动态属性的方法 方式一: # ===========方式一================ class Foo(object): user ...
- Flask学习【第10篇】:自定义Form组件
wtforms源码流程 实例化流程分析 1 # 源码流程 2 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: meta类读取到cls._ ...
- Tronado【第2篇】:tronado自定义Form组件
Tronado自定义Form组件 一.获取类里面的静态属性以及动态属性的方法 方式一: # ===========方式一================ class Foo(object): user ...
- Flask【第10篇】:自定义Form组件
自定义Form组件 一.wtforms源码流程 1.实例化流程分析 1 # 源码流程 2 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: ...
- BBS论坛 自定义form组件
二.自定义form组件 from django import forms from django.forms import widgets from app01 import models # 定制f ...
- Flask系列(十)自定义Form组件
一.wtforms源码流程 1.实例化流程分析 # 源码流程 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: meta类读取到cls._ ...
- 基于wtforms源码实现自定义form组件
from flask import Flask,Markup,render_template,request,redirect from wtforms.form import Form from w ...
- 基于Django Form源码开发自定义Form组件
import copy import re class ValidateError(Exception): def __init__(self, detail): self.detail = deta ...
随机推荐
- mybatis批量更新报错
批量更新sql <update id="updateAutoAppraiseInfo" parameterType="Object"> <fo ...
- 2017-2018-2 165X 『Java程序设计』课程 团队项目备选题目
2017-2018-2 165X 『Java程序设计』课程 团队项目备选题目 结合本课程时间安排,以及同学们的专业和课程内容,制定了以下六个题目供各小组选择.如有其他项目方案设想,可自行与老师沟通.老 ...
- 【try..catch..】【判断输入是否为空】【onchange事件】【onmouseover和onmouseout事件】【onmousedown和onmouseup事件】
1.try..catch.. <body><script>function myFunction(){try{ var x=document.getElementById(&q ...
- js-ES6学习笔记-Set和Map数据结构
1.ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来生成 Set 数据结构. 2.Set 函数可以接受一个数组(或类似数组的对 ...
- Configuring Automatic Restart of an Oracle Database
https://docs.oracle.com/cd/E11882_01/server.112/e25494/restart.htm#ADMIN12708
- ansible 常见指令表
Play 指令 说明 accelerate 开启加速模式 accelerate_ipv6 是否开启ipv6 accelerate_port 加速模式的端口 always_run any_error ...
- python3+requests库框架设计03-请求重新封装
在完成了日志类封装之后,那我们就要对测试基类进行实现,在其中对一些请求再次封装,在项目下新建一个Common文件夹,在文件夹下新建Base_test.py文件,项目结构如下. 具体怎么封装还是要看被测 ...
- 理解OAuth 2.0(转)
OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版. 本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料 ...
- struts2框架之文件下载(参考第三天学习笔记)
下载 1. 下载是一种响应方式 正常的响应:响应正文是html:response.getWriter().print("html"); 下载的响应: 1.一个流:字节数据:resp ...
- 统一门户与业务系统的sso整合技术方案(单点登录)
一.单点登录(SSO,Single Sign On)整合目前计划接入统一门户的所有业务系统均为基于JavaEE技术的B/S架构系统.由于统一门户的单点登录技术选用的是JA-SIG组织开发的Cas Se ...