基于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 "<input type='text' name='name'/>"

class TextErea():
    def __call__(self, *args, **kwargs):
        return '<textarea name="email"> </textarea>'
#字段
class Field():

    def __str__(self):
        return Markup(self.widget())


class StringField(Field):
    widget=TextInput()


    def validate(self,data):
        if data:
            return True

class EmailField(Field):
    widget=TextErea()


    def validate(self,data):
        reg = ".*@.*"
        import re
        if re.match(reg,data):
            return True
#Form
class BaseForm(object):
    def __init__(self,*args,**kwargs):
        _fields={}
        for name,field in self.__class__.__dict__.items():
            if isinstance(field,Field):
                _fields[name]=field

        self._fields=_fields
        self.data={}


    def validate(self,form_data):
        flag=True
        for name,field in self._fields.items():
            input_val=form_data.get(name,'')
            result=field.validate(input_val)
            if not result:
                flag=False
            else:
                self.data[name]=input_val
        return flag


class LoginForm(BaseForm):
    name=StringField()
    email=EmailField()



app=Flask(__name__)

@app.route('/login',methods=['GET','POST'])
def login():
    if request.method=='GET':
        form=LoginForm()
        return  render_template('login.html',form=form)
    else:
        form=LoginForm()
        if form.validate(request.form):
            print('login success')
            return 'hello'
        return redirect('/login')


if __name__ == '__main__':
    app.run()
View Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
<form  method="post">
   {{ form.name }}
    {{ form.email }}
    <input type="submit">
  </form>  
</body>
</html>
View Code

根据源码可以看出,实际上请求的流程可以分为三个大类:Form,插件Widget,,字段Field,用到的更多是面向对象的知识

原文地址:https://www.cnblogs.com/ctztake/p/8260525.html