Flask【第10篇】:自定义Form组件
自定义Form组件
一、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. 执行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 = 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组件

#!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()

Flask【第10篇】:自定义Form组件的更多相关文章
- Flask学习【第10篇】:自定义Form组件
wtforms源码流程 实例化流程分析 1 # 源码流程 2 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: meta类读取到cls._ ...
- Tronado【第2篇】:tronado自定义Form组件
Tronado自定义Form组件 一.获取类里面的静态属性以及动态属性的方法 方式一: # ===========方式一================ class Foo(object): user ...
- 仿照wtform自定义Form组件
仿照wtforms自定义Form组件 1.wtforms 点击查看源码分析及使用方法 2.自定义Form组件 #!usr/bin/env python # -*- coding:utf-8 -*- f ...
- 自定义Form组件
一.wtforms源码流程 1.实例化流程分析 # 源码流程 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: meta类读取到cls._ ...
- Tronado自定义Form组件
Tronado自定义Form组件 一.获取类里面的静态属性以及动态属性的方法 方式一: # ===========方式一================ class Foo(object): user ...
- 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 ...
- flask第十一篇——自定义url转换器
首先和大家说一下flask的组成,flask其实是werkzeug(路由和http处理)+SQLAlchemy(数据库)+Jinja2(模板)组成的,今天我们要看到的东西就是`werkzeug`里面的 ...
随机推荐
- 缓存融合(Cache Fusion)介绍
概念 简单地说,缓存融合就是把Oracle RAC数据库中所有数据库缓存作为一个共享的数据库缓存,并被RAC中的所有节点共享.它是实现RAC的基本技术. 缓存融合主要有如下四个功能: (1) 提供扩展 ...
- 在Windows服务器安装ss服务端用于逃脱公司行为管理
1.安装:python-2.7.14.amd64.msi 2.配置环境变量 3.Win64OpenSSL-1_0_2n.exe 4.安装ss服务端:pip install **adowsocks 5. ...
- react native配置ip真机测试
首先保证真机和pc 保证在同一个网络下 根据红色错误判断自己是什么情况 例如 提示无法连接远程服务,说明你的不在同一网络下 提示500 可能配置的ip不对 设置ip方法 摇晃手机 ---> De ...
- SVM的推导和理解
主要记录了SVM思想的理解,关键环节的推导过程,主要是作为准备面试的需要. 1.准备知识-点到直线距离 点\(x_0\)到超平面(直线)\(w^Tx+b=0\)的距离,可通过如下公式计算: \[ d ...
- 【VS开发】使用WinPcap编程(2)——打开网络设备并且开始捕获数据包
这里需要特别强调的一个数据结构是pcap_t,它相当于一个文件描述符,代表一个已经打开的设备.我们对这个设备进行操作,就是对这个文件描述符进行操作. 首先是打开一个已知的设备,使用pcap_open( ...
- navicat连接 mysql报错1251解决方案
转自:https://blog.csdn.net/XDMFC/article/details/80263215 好不容易安装好mysql,但又出现了mysql客户端版本太低的问题.根据参考的这篇博客, ...
- 使用注解方式搭建SpringMVC
1.以前搭建Spring MVC 框架一般都使用配置文件的方式进行,相对比较繁琐.spring 提供了使用注解方式搭建Spring MVC 框架的方式,方便简洁.使用Spring IOC 作为根容器管 ...
- OSCHINA 公布 2019 年度最受欢迎中国开源软件
https://www.oschina.net/project 此文章从此处转载:https://www.oschina.net/project/top_cn_2019?utm_source=star ...
- 【字符串大模拟】潜伏者—— NOIP2009原题
洛谷连接 就一道黄题没啥可以说的……就是要细心…… 学到了神奇的优化 ios::sync_with_stdio(false); cin优化,能跑的比scanf快!棒!(不过要开std) 这题真的还挺简 ...
- 如何用vue封装一个防用户删除的平铺页面的水印组件
需求 为了防止截图等安全问题,在web项目页面中生成一个平铺全屏的水印 要求水印内容为用户名,水印节点用户不能通过开发者工具等删除 效果 如上图 在body节点下插入水印DOM节点,水印节点覆盖在页面 ...