wtforms
是 Python
的表单组件,用于表达数据的验证。
pip3 install wtforms
wtforms
依照功能类别来说wtforms
分别由以下几个类别:
Forms
: 主要用于表单验证、字段定义、HTML
生成,并把各种验证流程聚集在一起进行验证。Fields
: 主要负责渲染(生成HTML
)和数据转换。Validator
:主要用于验证用户输入的数据的合法性。比如Length
验证器可以用于验证输入数据的长度。Widgets
:html插件,允许使用者在字段中通过该字典自定义html
小部件。Meta
:用于使用者自定义wtforms
功能,例如csrf
功能开启。Extensions
:丰富的扩展库,可以与其他框架结合使用,例如django
。Flask
信号机制(signal
)Forms
进行表单验证首先给出一个简单的示例程序,web
部分使用的是 Flask
,换成 tornado
、aiohttp
等都是一样的。
# coding=utf-8
from flask import Flask, request
from multidict import MultiDict
from wtforms import Form, StringField, validators, ValidationError
# 定义 app 实例
app = Flask(__name__)
# 表单验证类
class ActionForm(Form):
action = StringField('action', [validators.DataRequired()])
@app.route("/test", methods=['POST'])
def action():
post_data = request.json
_form = ActionForm(MultiDict(post_data))
if _form.validate():
print('>>>> {} validate success'.format(post_data))
return "form success"
else:
print('<<<< {}'.format(_form.errors))
return "form validate"
if __name__ == '__main__':
app.run(debug=True)
使用 curl 进行测试:
curl -l -H "Content-type: application/json" -X POST -d '{"action": "START"}' 127.0.0.1:5000/test
>>> form success
说明:
ActionForm
类,用于验证一个类型为String
的字段,字段名为action
**, validators.DataRequired()
表示该字段必须要有,若无则无法通过验证,validators.optional()
表示该参数可选;post_data
中有其他参数未在**ActionForm
**定义的话,不会影响form
的验证,直接忽略;StringField
外,还有其他如:BooleanField
、DateField
、IntegerField
、PasswordField
、FieldList
、FormField
,FloatField
等等,可以查看官方文档;FieldList
**是一个列表字段,可以指定list
中field
的类型;FormField
**类似一个字典字段,可以嵌套定义;Form
后,调用**validate()
进行验证,若通过验证则返回True
,否则返回False
,失败的情况加Form
的errors
**返回所有所有验证失败的字段及失败信息;Costom validators
在使用过程中,会有需求对字段进行更细化的验证,比如:希望**action
字段的字符串值在['START', 'CANCEL']
**范围内,此时就需要编写自定义的验证函数,对字段进行追加验证。
增加一个validator
,用于验证action
字段在['START', 'CANCEL']
范围内,若不在则抛出**ValidationError
**异常:
def my_action_check(form, field):
if field.data not in ['START', 'CANCEL']:
raise ValidationError('action must in [START, CANCEL]')
在**ActionForm
的action
字段的validator
列表中加入my_action_check
**,wtForms
会按照先后顺序调用所有的validator
对字段进行验证(链式调用,某个环节失败则不继续验证)
class ActionForm(Form):
action = StringField('action', [validators.Required(), my_action_check])
action
参数不为START
或CANCEL
**,则表单无法通过验证。form
字段即为当前的form
对象,可用来获取其他字段的值进行联合验证field
字段即为当前的字段对象,通过field.data
来获取值这里的my_action_check
方式是定义在ActionForm
类的外部,当然也可以将其定义在ActionForm
类的内部,如下所示:
class ActionForm(Form):
action = StringField('action', [validators.Required()])
def validate_action(form, field):
if field.data not in ['START', 'CANCEL']:
raise ValidationError('action must in [START, CANCEL]')
这两种验证方式的效果都是一样的,可以根据实际情况选择,若my_action_check
具有通用性,则可就想起定义在外部,同时在在多个验证类中引用。若my_action_check
是针对某个字段的特定验证,则将其定义在验证类内部方便维护。
Costom Fields
有的场景下,会post
复杂的json
数据,wtForms
自带的字段会感觉不太够用,此时可以自己定义一个字段,能灵活验证数据。如嫌**FieldList
或者FormField
**用起来麻烦,可以自己定义一个ListField
、DictField
来验证列表和字典字段。
自定义ListField
,验证数组:
class ListField(Field):
def process_formdata(self, valuelist):
try:
if valuelist[0] and isinstance(valuelist[0], list):
self.data = valuelist[0]
else:
raise ValidationError('list validate error')
except:
raise ValidationError('list validate error, exception')
class ActionForm(Form):
action = StringField('action', [validators.DataRequired()])
users = ListField('users', [validators.DataRequired()])
def validate_action(form, field):
if field.data not in ['START', 'CANCEL']:
raise ValidationError('action must in [START, CANCEL]')
使用 crul 进行测试:
curl -l -H "Content-type: application/json" -X POST -d '{"action": "START", "users": ["Tracy", "Kobe", "KD"]}' 127.0.0.1:5000/test
>>> form success
users
字段不传数组或数组为空则form无法通过验证
ListField
时,需重process_formdata
方法处理初始化时传入的值,值通过valuelist[0]
获取,若验证通过则将值赋给self.data
,那么这个字段就有值了,后续的validators
就可以对此值进行验证validators.DataRequired()
实际做的事情就是判断字段的self.data
是否为True
wtForms
还有一些其他用法在此就不再介绍了,翻阅文档吧。