对flask中的wtforms验证和异常处理

from views import app

from wtforms import Form, StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired, Length, Email, Regexp, EqualTo, Optional, AnyOf
from flask import jsonify,request
from wtforms import ValidationError   #这里我使用wtforms自带的验证异常类,然后绑定到flask程序中


#异常路由的处理过程
'''
第一步:定义一个自己的异常类
第二步:将flask错误路由勾着异常类(钩子)
第三步:手动触发自己的异常类,然后就会自动触发钩子的错误路由函数。钩子路由函数对错误进行解释说明然后返回前端可用的信息
'''


'''这个异常类有两个目的,是主动引起异常和异常挂载的接口,定义这个类才能引起这个类的异常,定义这个类才能绑定路由异常捕获。当异常发生时就可以经过flask路由处理函数了。'''
'''定义请求异常类,需要手动触发'''
# class MyValidationError(ValueError):    #也可以自定义异常类,主动触发然后让钩子路由处理
#     """定义验证异常错误."""
#     pass


'''这个类是定义表单验证的'''
#定义验证表单,可定义多个
class ComboCreateFrom(Form):     #验证的话可以直接实例化一个类,然后使用form(data=data)验证
    #注意所有验证的字段必须在表内,如果关键字不在关键字就被剔除了
    user_name = StringField('user_name', validators=[DataRequired(message="用户姓名必填"),
                                                     Length(min=2, max=12, message="用户名长度必须为2至12位")])
    user_phone = StringField('user_phone', validators=[DataRequired(message="电话号码必填"),
                                                       Regexp(r'^1[35789]\d{9}$',message="请输入11位手机号")])
    user_school = StringField('user_school', validators=[DataRequired(message="学校必填")])


'''能够统一整合不同的form用来验证request—data数据'''
#验证数据的合理性,不合理直接触发异常,然后由钩子函数处理
#这个类的主要目的是Form验证数据,然后进一步手动引发自己定义的异常类。:如果是这样,为什么不直接绑定到Form表单的异常路由,而不是手动引起的异常路由。暂时留着,可以会有更大的用处
class RequestForm(object):         #定义统一的表单验证类,目的为为了验证后返回统一的格式,不然需要一个个改所有。 传入任意的Form和任意data。Form就能验证对应的Data数据值了。
    def __init__(self, form, request):
        self.request = request
        self.form = form
        if "application/json" in request.headers.get("Content-Type", ""):
            self.data = request.json
            self.args = request.args.to_dict()
        else:
            self.args = request.args.to_dict()
            form_dict = request.form.to_dict()
            check_form = form_dict.values()
            if len(check_form) == 1:
                self.data = dict()
                for key, value in form_dict.items():
                    if value == "" and len(key) > 5 and "{" in key:
                        try:
                            self.data = eval(key)
                        except SyntaxError as e:
                            #手动触发ValidationError为这个异常类,触发后就关联到Flask这个钩子了,这个钩子勾着这个异常
                            raise ValidationError("error received request from not a json {}".format(key))
                    else:
                        self.data.update({key: value})
            else:
                self.data = form_dict
            if not self.data and self.args:
                self.data = self.args

    def validate(self):          #验证form接受data的格式,如果验证不通过就直接收到引发异常,然后统一设置返回格式
        if not self.data:
            raise ValidationError("error received request from not a json")
        for key, value in self.data.items():
            if value and isinstance(value, str) and value[0] == "[" and value[-1] == "]":
                self.data[key] = eval(value)
        from_obj = self.form(data=self.data)          #核心代码:使用form验证字段内容的正确性
        from_obj.validate()
        if from_obj.errors:
            raise ValidationError(from_obj.errors)    #也可以自定义一个继承其他异常类的类,然后手动触发,然后发给绑定的路由函数
            #raise MyValidationError(from_obj.errors)  #手触发自己定义的异常类,但是没有
        return from_obj.data




'''钩子路由函数'''
#挂载自己定义的异常类,如果。定义flask的钩子,勾着ValidationError这个异常类,主动抛出这个异常的时候就调用下面函数
@app.errorhandler(ValidationError)   #定义错误路由,和一般的路由完全一样,只不过传入了一个e错误参数
def validation_error(e):  #
    """表单验证错误."""
    response = jsonify({'code': 400, 'message':e.args, 'data': {}})  #code表示状态码,data表示正常发送时传入的数据,message表示异常数据时发送的数据
    print(e.args)    #打印接受后的异常信息
    response.status_code = 200
    response.headers["Access-Control-Allow-Origin"] = "*"
    response.headers["Content-Type"] = "application/json; charset=utf-8"   #这两行好像是设置什么跨域请求,暂时不太清楚
    return response


'''
验证测试代码
curl -H "Content-Type: application/json" -X POST -d '{"user_name": "123", "coin":100, "success":1, "msg":"OK!" }' "http://localhost:5000/tijiao"
'''



#404错误等code代码错误不用定义类型绑定直接传入响应头数据也可以直接钩子触发

@app.errorhandler(404)  
def page_not_found(error):
    return '---Not Found---', 404



@app.route("/tijiao",methods=["POST"])
def tijiao():
    print(request.get_json())
    form = RequestForm(form=ComboCreateFrom, request=request)
    form.validate()
    return "数据正常返回",200

if __name__=="__main__":
    app.run()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值