一、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 class
  16. # 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.default
  38.  
  39. self.object_data = data
  40.  
  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__ 方法,返回标签字符串

2、验证流程分析

  1. a. 执行formvalidate方法,获取钩子方法
  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 = None
  13. success = True
  14. 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 = False
  21. return success
  22. c. 每个字段进行验证时候
  23. 字段的pre_validate 【预留的扩展】
  24. 字段的_run_validation_chain,对正则和字段的钩子函数进行校验
  25. 字段的post_validate【预留的扩展】

二、自定义Form组件

  1. #!usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from flask import Flask,render_template,request,Markup
  4. app = Flask(__name__,template_folder="templates")
  5. app.debug = True
  6. # ==============通过这几个类就可以显示了-==============
  7. #插件
  8. class Widget(object):
  9. pass
  10.  
  11. class InputText(Widget):
  12. def __call__(self, *args, **kwargs):
  13.  
  14. return "<input type='text' name='name'>"
  15.  
  16. class TextArea(Widget):
  17. def __call__(self, *args, **kwargs):
  18. return Markup("<textarea name='email'></textarea>")
  19.  
  20. #Form
  21. class BaseForm(object):
  22. def __init__(self):
  23. #获取当前所有的字段
  24. _fields = {}
  25. for name, field in self.__class__.__dict__.items():
  26. if isinstance(field, Field): # 筛选出字段是name和emailDe
  27. _fields[name] = field
  28. self._fields = _fields
  29. self.data = {}
  30. # print(_fields) # {'name': 111, 'email': 222}
  31.  
  32. def validate(self,request_data):
  33. #先找到所有的字段,在执行每一个字段的validate方法
  34. flag = True
  35. for name, field in self._fields.items():
  36. input_val = request_data.get(name,"") #用户输入的值
  37. result= field.validate(input_val) #每一个字段自己校验
  38. print("???????????",input_val,result)
  39. if not result:
  40. flag = False
  41. else:
  42. self.data[name] = input_val
  43. return flag
  44. #字段
  45. class Field(object):
  46. '''所有类的基类'''
  47. def __str__(self): #python中的静态字段通过类能找到,通过对象也能找到
  48. return Markup(self.widget()) #self就是StringField,self
  49.  
  50. class StringField(Field): #每个字段打印的时候都要去执行__str__,所以选择放在基类里面,自己没有就调用父类的
  51. widget = InputText()
  52. def validate(self,val):
  53. if val:
  54. return True
  55.  
  56. class EmaliField(Field):
  57. widget = TextArea()
  58. reg = ".*@.*"
  59.  
  60. def validate(self,val):
  61. import re
  62. print(re.match(self.reg,val),"************")
  63. if re.match(self.reg,val):
  64. return True
  65.  
  66. # ===============使用===============
  67. class LoginForm(BaseForm):
  68. name = StringField()
  69. email = EmaliField()
  70.  
  71. @app.route('/index', methods=["GET","POST"])
  72. def index():
  73. form = LoginForm()
  74. ret = form.validate(request.form)
  75. print("验证成功",ret)
  76. print("验证成功的值",form.data)
  77. # print(form.name)
  78. # print(form.email)
  79. return render_template("index.html",form=form)
  80.  
  81. if __name__ == '__main__':
  82. app.run()

自定义Form组件的更多相关文章

  1. 仿照wtform自定义Form组件

    仿照wtforms自定义Form组件 1.wtforms 点击查看源码分析及使用方法 2.自定义Form组件 #!usr/bin/env python # -*- coding:utf-8 -*- f ...

  2. Tronado自定义Form组件

    Tronado自定义Form组件 一.获取类里面的静态属性以及动态属性的方法 方式一: # ===========方式一================ class Foo(object): user ...

  3. Flask学习【第10篇】:自定义Form组件

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

  4. Tronado【第2篇】:tronado自定义Form组件

    Tronado自定义Form组件 一.获取类里面的静态属性以及动态属性的方法 方式一: # ===========方式一================ class Foo(object): user ...

  5. Flask【第10篇】:自定义Form组件

    自定义Form组件 一.wtforms源码流程 1.实例化流程分析 1 # 源码流程 2 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: ...

  6. BBS论坛 自定义form组件

    二.自定义form组件 from django import forms from django.forms import widgets from app01 import models # 定制f ...

  7. Flask系列(十)自定义Form组件

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

  8. 基于wtforms源码实现自定义form组件

    from flask import Flask,Markup,render_template,request,redirect from wtforms.form import Form from w ...

  9. 基于Django Form源码开发自定义Form组件

    import copy import re class ValidateError(Exception): def __init__(self, detail): self.detail = deta ...

随机推荐

  1. mybatis批量更新报错

    批量更新sql <update id="updateAutoAppraiseInfo" parameterType="Object"> <fo ...

  2. 2017-2018-2 165X 『Java程序设计』课程 团队项目备选题目

    2017-2018-2 165X 『Java程序设计』课程 团队项目备选题目 结合本课程时间安排,以及同学们的专业和课程内容,制定了以下六个题目供各小组选择.如有其他项目方案设想,可自行与老师沟通.老 ...

  3. 【try..catch..】【判断输入是否为空】【onchange事件】【onmouseover和onmouseout事件】【onmousedown和onmouseup事件】

    1.try..catch.. <body><script>function myFunction(){try{ var x=document.getElementById(&q ...

  4. js-ES6学习笔记-Set和Map数据结构

    1.ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来生成 Set 数据结构. 2.Set 函数可以接受一个数组(或类似数组的对 ...

  5. Configuring Automatic Restart of an Oracle Database

    https://docs.oracle.com/cd/E11882_01/server.112/e25494/restart.htm#ADMIN12708

  6. ansible 常见指令表

    Play 指令 说明 accelerate 开启加速模式 accelerate_ipv6 是否开启ipv6 accelerate_port 加速模式的端口 always_run   any_error ...

  7. python3+requests库框架设计03-请求重新封装

    在完成了日志类封装之后,那我们就要对测试基类进行实现,在其中对一些请求再次封装,在项目下新建一个Common文件夹,在文件夹下新建Base_test.py文件,项目结构如下. 具体怎么封装还是要看被测 ...

  8. 理解OAuth 2.0(转)

      OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版. 本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料 ...

  9. struts2框架之文件下载(参考第三天学习笔记)

    下载 1. 下载是一种响应方式 正常的响应:响应正文是html:response.getWriter().print("html"); 下载的响应: 1.一个流:字节数据:resp ...

  10. 统一门户与业务系统的sso整合技术方案(单点登录)

    一.单点登录(SSO,Single Sign On)整合目前计划接入统一门户的所有业务系统均为基于JavaEE技术的B/S架构系统.由于统一门户的单点登录技术选用的是JA-SIG组织开发的Cas Se ...