簡體   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