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

wtforms源码流程

实例化流程分析

 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__ 方法,返回标签字符串

验证流程分析

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

  

原文地址:https://www.cnblogs.com/596014054-yangdongsheng/p/10228955.html

时间: 2024-08-27 17:11:31

Flask学习【第10篇】:自定义Form组件的相关文章

Flask系列(十)自定义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

Flask 【第十篇】自定义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

自定义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.

tornado自定义Form组件

一.获取类里面的静态属性以及动态属性的方法 方式一: # ===========方式一================ class Foo(object): user = 123 def __init__(self): self.name = 123 self.age = 456 def aaa(self): self.name = 'sd' obj = Foo() # print(obj.__dict__) #获取对象属性 # print(Foo.__dict__) #获取类里面的所有属性以及

Django 【第十一篇】Form组件基础

一.model常用操作 1.13个API查询:all,filter,get ,values,values_list,distinct,order_by ,reverse , exclude(排除),count,first,last,esits(判断是否存在) 需要掌握的all.values.values_list的区别 all:打印的是一个QuerySet集合,一个列表里面放的对象 values :是一个字典形式 values_list:是一个元组形式 all的性能是最低的 2.only和def

Flask 【第八篇】flask-session组件

简介 flask-session是flask框架的session组件,由于原来flask内置session使用签名cookie保存,该组件则将支持session保存到多个地方,如: redis:保存数据的一种工具,五大类型.非关系型数据库 memcached filesystem mongodb sqlalchmey:那数据存到数据库表里面 安装 pip3 install flask-session 存储方式 redis #!/usr/bin/env python # -*- coding:ut

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

from flask import Flask,Markup,render_template,request,redirect from wtforms.form import Form from wtforms.fields import core from wtforms import widgets #插件 class Widget(object): pass class TextInput(): def __call__(self, *args, **kwargs): return "&

Django 【第十二篇】Form组件进阶

一.定义的规则 class TeacherForm(Form): #必须继承Form # 创建字段,本质上是正则表达式 username = fields.CharField( required=True, #必填字段 error_messages={"required":"用户名不能为空!!"}, #显示中文错误提示 widget=widgets.TextInput(attrs={"placeholder":"用户名",&q

Django 【第十三篇】Form组件归类

一.Form类 创建Form类时,主要涉及到 [字段] 和 [插件],字段用于对用户请求数据的验证,插件用于自动生成HTML; 1.Django内置字段如下: Field required=True, 是否允许为空 widget=None, HTML插件 label=None, 用于生成Label标签或显示内容 initial=None, 初始值 help_text='', 帮助信息(在标签旁边显示) error_messages=None, 错误信息 {'required': '不能为空',