繁体   English   中英

使用 Pydantic 的 Sanic 请求验证:处理 uri 时发生异常:

[英]Sanic request validation using Pydantic: Exception occurred while handling uri:

我按照https://sanic.dev/en/plugins/sanic-ext/validation.html#validation-with-pydantic中的示例使用 Pydantic 对我的 Sanic 路由实施验证。

如果我使用有效的请求参数向路由发出请求,代码将成功执行,没有问题。

如果我使用不符合 Pydantic 'ValidatePayment' class 定义的 'payment' 参数向路由发出请求,Sanic 会响应指示验证错误的请求,如下所示:

{
  "description": "Bad Request",
  "status": 400,
  "message": "Invalid request body: ValidatePayment. Error: 1 validation error for ValidatePayment\npayment\n  invalid payment... (type=value_error)"
}

到目前为止,这很好,但是,当 Sanic 以上述验证错误响应时,它还会向控制台抛出/输出以下异常,表明未正确捕获/处理多个异常:

| [2022-03-27 17:45:38 +0000] [8] [ERROR] Exception occurred while handling uri: 'http://localhost:5001/pay'
| Traceback (most recent call last):
|   File "/usr/local/lib/python3.9/site-packages/sanic_ext/extras/validation/validators.py", line 24, in validate_body
|     return validator(model, body)
|   File "/usr/local/lib/python3.9/site-packages/sanic_ext/extras/validation/validators.py", line 32, in _validate_instance
|     return model(**body)
|   File "pydantic/main.py", line 331, in pydantic.main.BaseModel.__init__
| pydantic.error_wrappers.ValidationError: 1 validation error for ValidatePayment
| payment
|   invalid payment... (type=value_error)
| 
| During handling of the above exception, another exception occurred:
| 
| Traceback (most recent call last):
|   File "handle_request", line 83, in handle_request
|     )
|   File "/usr/local/lib/python3.9/site-packages/sanic_ext/extensions/openapi/openapi.py", line 213, in handler
|     retval = await retval
|   File "/usr/local/lib/python3.9/site-packages/sanic_ext/extras/validation/decorator.py", line 37, in decorated_function
|     await do_validation(
|   File "/usr/local/lib/python3.9/site-packages/sanic_ext/extras/validation/setup.py", line 41, in do_validation
|     validation = validate_body(validator, model, data)
|   File "/usr/local/lib/python3.9/site-packages/sanic_ext/extras/validation/validators.py", line 26, in validate_body
|     raise ValidationError(
| sanic_ext.exceptions.ValidationError: Invalid request body: ValidatePayment. Error: 1 validation error for ValidatePayment

如果可能的话,我将很高兴知道为什么控制台中会出现此异常,以及我该如何正确处理它。

这是路由定义的代码:

@app.route("/pay", methods=['POST'])
@validate(json=ValidatePayment)
async def pay(request):

    ...

    response = {
        "status": 200,
        ...
    }

    return json(response, 200)

这是 Pydantic 验证的代码 class:

from pydantic import BaseModel, validator

class ValidatePayment(BaseModel):
    payment: str

    @validator('payment')
    def valid_payment(cls, v):
        if v[0:4] != "...." and v[0:4] != "----":
            raise ValueError(f'invalid payment...')
        return v

所以经过更多的搜索和阅读,我想出了两种可能的解决方案。

第一种是使用 app.exception 装饰器向每个单独的路由添加自定义异常处理,或者作为一个单一的包罗万象的处理程序,如下所述: https:https://sanic.dev/en/guide/best-practices /exceptions.html#handling

然而,一个更简洁的解决方案似乎是让 Pydantic 验证 class 引发 SanicException,而不是引发 ValueError。 例如,这个:

from pydantic import BaseModel, validator

class ValidatePayment(BaseModel):
    payment: str

    @validator('payment')
    def valid_payment(cls, v):
        if v[0:4] != "...." and v[0:4] != "----":
            raise ValueError(f'invalid payment...')
        return v

变成这样:

from pydantic import BaseModel, validator
from sanic.exceptions import SanicException

class ValidatePayment(BaseModel):
    payment: str

    @validator('payment')
    def valid_payment(cls, v):
        if v[0:4] != "...." and v[0:4] != "----":
            raise SanicException('Invalid payment...', status_code=400)
        return v

这样做时,客户端仍然收到验证失败通知,并且Sanic控制台/日志中没有未处理的异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM