第四章:(反)序列化篇

表单验证

__init__中对请求的content_type做了验证,支持application/x-www-form-urlencodedmultipart/form-dataapplication/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()]}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

llc的足迹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值