表单验证
__init__
中对请求的content_type
做了验证,支持application/x-www-form-urlencoded
、multipart/form-data
、application/json
三种类型的验证,但是,当参数中有类似[1,2,3]
的列表参数时,wtforms
无法处理,需要在初始化之前将参数值转换为list object
,故而实现了string2list
方法。
import traceback
from flask import request
from wtforms import Form
from app.utils.exceptions import ParameterException
class BaseForm(Form):
"""表单、参数验证基类"""
def __init__(self):
content_type = request.content_type
if content_type == 'application/x-www-form-urlencoded':
data = request.form.to_dict()
elif 'multipart/form-data' in str(content_type):
data = request.form.to_dict()
elif content_type == 'application/json':
data = request.json
else:
data = {}
args = request.args.to_dict()
if hasattr(self, 'key_list'):
# content-type为multipart/form-data或application/x-www-form-urlencoded时:
# 将string转化为list object
kwargs = self.string2list()
data.update(**kwargs)
print(data, args)
super(BaseForm, self).__init__(data=data, **args)
def validate_for_api(self):
try:
valid = super(BaseForm, self).validate()
except Exception as e:
traceback.print_exc(e)
raise ParameterException(message='参数验证错误')
if not valid:
raise ParameterException(message=self.errors)
return self
def string2list(self):
kwargs = {}
for key in self.key_list:
value = request.form.get(key)
if value is None:
continue
try:
assert value.startswith('[')
assert value.endswith(']')
kwargs[key] = list(eval(value))
except:
raise ParameterException(message=f'参数错误:{key}')
return kwargs
要将string
类型的列表转化为list object
,必须在子类中添加key_list
属性:
class AddUserForm(BaseForm):
name = StringField(validators=[DataRequired(), length(min=4, max=32)])
password = PasswordField(validators=[DataRequired(), EqualTo('confirm_password'), length(min=6)])
confirm_password = PasswordField(validators=[DataRequired()])
email = StringField(
validators=[
Regexp(r'^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$'),
Optional()
])
role_ids = FieldList(IntegerField(validators=[DataRequired()]), default=[1])
key_list = ['role_ids']
序列化
序列化实现采用了比较简单的方式,在每个model
中实现data
方法:
class User(Base):
name = db.Column(db.String(32), unique=True, nullable=False, comment='用户名')
email = db.Column(db.String(32), unique=True, nullable=True, comment='邮箱')
is_admin = db.Column(db.Boolean, unique=False, nullable=False, default=False, comment='是否是超级管理员')
# is_active = db.Column(db.Boolean, unique=False, nullable=False, default=True, comment='是否激活')
roles = db.relationship('Role', secondary=user_role, backref=db.backref('users', lazy='dynamic'), lazy='dynamic')
_password = db.Column('password', db.String(100), comment='密码')
...
def data(self):
return {'id': self.id, 'name': self.name, 'email': self.email,
'roles': [role.data() for role in self.roles.all()]}