使用 pydatinc 对 FastAPI 的查询参数进行自定义验证会导致内部服务器错误

问题描述 投票:0回答:1

我的

GET
端点收到需要满足以下条件的查询参数:

  1. 是 0 到 10 之间的
    int
  2. 是偶数

1.
可以直接使用
Query(gt=0, lt=10)
。但是,我不清楚如何扩展
Query
来进行额外的自定义验证,例如
2.
。该文档最终导致了 pydantic。但是,当第二次验证
2.
失败时,我的应用程序遇到内部服务器错误。

下面是一个最小范围的示例

from fastapi import FastAPI, Depends, Query
from pydantic import BaseModel, ValidationError, validator

app = FastAPI()

class CommonParams(BaseModel):
    n: int = Query(default=..., gt=0, lt=10)

    @validator('n')
    def validate(cls, v):
        if v%2 != 0:
            raise ValueError("Number is not even :( ")
        return v


@app.get("/")
async def root(common: CommonParams = Depends()):
    return {"n": common.n}

以下是按预期工作的请求和失败的请求:

# requsts that work as expected
localhost:8000?n=-4
localhost:8000?n=-3
localhost:8000?n=2
localhost:8000?n=8
localhost:8000?n=99

# request that break server
localhost:8000?n=1
localhost:8000?n=3
localhost:8000?n=5
python exception fastapi valueerror pydantic
1个回答
1
投票

选项1

直接提高

HTTPException
而不是
ValueError
,如此答案的选项1所示。示例:

from fastapi import FastAPI, Depends, Query, HTTPException
from pydantic import BaseModel, validator

app = FastAPI()

class CommonParams(BaseModel):
    n: int = Query(default=..., gt=0, lt=10)

    @validator('n')
    def prevent_odd_numbers(cls, v):
        if v % 2 != 0:
            raise HTTPException(status_code=422, detail='Input number is not even')
        return v


@app.get('/')
async def root(common: CommonParams = Depends()):
    return {'n': common.n}

服务器响应(当输入数字非偶数时,例如

n = 1
):

# 422 Error: Unprocessable Entity

{
  "detail": "Input number is not even"
}

选项2

使用自定义异常处理程序,以处理

ValueError
异常,类似于这个答案这个答案。示例:

from fastapi import FastAPI, Request, Depends, Query, status
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel, validator

app = FastAPI()

@app.exception_handler(ValueError)
async def validation_exception_handler(request: Request, exc: ValueError):
    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content=jsonable_encoder({"detail": exc.errors(),  # optionally, include the pydantic errors
                 "custom msg": {"Your error message"}}),   # optionally, return a custom message
    )
    
class CommonParams(BaseModel):
    n: int = Query(default=..., gt=0, lt=10)

    @validator('n')
    def prevent_odd_numbers(cls, v):
        if v % 2 != 0:
            raise ValueError('Input number is not even')
        return v


@app.get('/')
async def root(common: CommonParams = Depends()):
    return {'n': common.n}

服务器响应(当输入数字非偶数时,例如

n = 1
):

# 422 Error: Unprocessable Entity

{
  "detail": [
    {
      "loc": [
        "n"
      ],
      "msg": "Input number is not even",
      "type": "value_error"
    }
  ],
  "custom msg": [
    "Your error message"
  ]
}

更新

请注意,在 Pydantic V2 中,

@validator
已被弃用,并被
@field_validator
取代。请查看此答案以获取更多详细信息和示例。

© www.soinside.com 2019 - 2024. All rights reserved.