flask_pydantic @validate 修改返回结果

367 阅读2分钟

前言

最近在用一个flask的校验框架:flask_pydantic,但是他的返回格式是固定的,大概如下,且框架自动处理了validate报错,就让flask的handerror捕捉不到他,让人很头疼,比如对我自己来说可能就不想返回url这个字段

{
    "validation_error": {
        "body_params": [
            {
                "input": {
                    "descri1ption": "11"
                },
                "loc": [
                    "name"
                ],
                "msg": "Field required",
                "type": "missing",
                "url": "https://errors.pydantic.dev/2.3/v/missing"
            },
            {
                "input": {
                    "descri1ption": "11"
                },
                "loc": [
                    "description"
                ],
                "msg": "Field required",
                "type": "missing",
                "url": "https://errors.pydantic.dev/2.3/v/missing"
            }
        ]
    }
}

然后他一共有四种校验参数:body_params,form_params,path_params,query_params,如果有值就返回,如果没有就不返回

方法

话不多说直接上操作: 通过查看flask_pydantic\core.py第238行可以发现他的错误处理机制是

  1. 如果 err 存在,说明出现了 Pydantic 校验错误。
  2. 如果 FLASK_PYDANTIC_VALIDATION_ERROR_RAISE 设置为 True,那么程序会抛出 FailedValidation 异常,并将校验错误信息作为异常的参数传递给异常类。
  3. 如果 FLASK_PYDANTIC_VALIDATION_ERROR_RAISE 设置为 False,那么程序会读取 FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE 配置选项来确定返回的 HTTP 状态码,默认为 400。然后,程序会使用 Flask 的 make_response 和 jsonify 方法来生成响应对象,将校验错误信息作为 JSON 数据放到响应体中,并返回给客户端。(这里就是我前文说的他自动处理了异常,导致handerror捕捉不到)
if err:
    if current_app.config.get(
        "FLASK_PYDANTIC_VALIDATION_ERROR_RAISE", False
    ):
        raise FailedValidation(**err)
    else:
        status_code = current_app.config.get(
            "FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE", 400
        )
        return make_response(
            jsonify({"validation_error": err}),
            status_code
        )

然后在第十四行可以看到FailedValidation是来自于.exception

from .exceptions import ValidationError as FailedValidation

所以我们可以在app.config设置FLASK_PYDANTIC_VALIDATION_ERROR_RAISE为True,然后再用handerror(ValidationError),就能捕获他抛出的异常了!如下

from flask_pydantic.exceptions import ValidationError

app = Flask(__name__)

app.config['FLASK_PYDANTIC_VALIDATION_ERROR_RAISE']=True


@app.errorhandler(ValidationError)
def validation_execution_handler(error):
    #捕捉flask_pydantic 的 validate()返回的错误,并且重写返回值(方便前端msg)
    body_params = error.body_params
    form_params = error.form_params
    path_params = error.path_params
    query_params = error.query_params
    msg = {}
    if body_params is not None:
        msg["body_params"] = [{k:v for k,v in params.items() if k != 'url' } for params in body_params]
    if form_params is not None:
        msg["form_params"] = [{k:v for k,v in params.items() if k != 'url' } for params in form_params]
    if path_params is not None:
        msg["path_params"] = [{k:v for k,v in params.items() if k != 'url' } for params in path_params]
    if query_params is not None:
        msg["query_params"] = [{k:v for k,v in params.items() if k != 'url' } for params in query_params]
    return jsonify({
        "code": 400,
        "msg": msg
    }), 400

validation_execution_handler(error):这一段代码可能有瑕疵,本文主要介绍如何捕捉flask_pydantic异常并自定义返回,如果觉得有用的话还请点赞