如何在 FastAPI 中使用 Pydantic 模型定义查询参数?

Ami*_* Ba 4 python openapi pydantic fastapi

我试图有一个像这样的端点/services?status=New

status将是 New或者Old

这是我的代码:

from fastapi import APIRouter, Depends
from pydantic import BaseModel
from enum import Enum

router = APIRouter()

class ServiceStatusEnum(str, Enum):
    new = "New"
    old = "Old"


class ServiceStatusQueryParam(BaseModel):
    status: ServiceStatusEnum


@router.get("/services")
def get_services(
  status: ServiceStatusQueryParam = Query(..., title="Services", description="my desc"),
):
    pass #my code for handling this route.....
Run Code Online (Sandbox Code Playgroud)

结果是我收到一个似乎与此问题相关的错误

错误说AssertionError: Param: status can only be a request body, using Body()


然后我找到了这里解释的另一个解决方案。

所以,我的代码将是这样的:

from fastapi import APIRouter, Depends
from pydantic import BaseModel
from enum import Enum

router = APIRouter()

class ServiceStatusEnum(str, Enum):
    new = "New"
    old = "Old"


class ServicesQueryParam(BaseModel):
    status: ServiceStatusEnum


@router.get("/services")
def get_services(
  q: ServicesQueryParam = Depends(),
):
    pass #my code for handling this route.....
Run Code Online (Sandbox Code Playgroud)

它正在工作(我不明白为什么) - 但问题是如何以及在哪里添加描述和标题?

Chr*_*ris 12

要创建 Pydantic 模型并使用它来定义查询参数,您需要Depends()与端点中的参数一起使用。要添加descriptiontitle等来查询参数,您可以将 包装Query()Field().

还应该注意的是,可以使用Literal类型来代替Enum,如此处此处所述。此外,如果想List在 Pydantic 模型中定义一个字段并将其用作查询参数,他们要么需要在单独的依赖项类中实现它,如此处和此处所示要么再次将其包装Query()在 a 中Field(),如图所示以下。

此外,要对 Pydnatic 模型内的查询参数进行验证,可以像往常一样使用 Pydantic 来执行此操作@validator,如此以及此处此处所示。请注意,在这种情况下,如果BaseModel将 用作查询参数,则引发ValueError将导致Internal Server Error. 因此,您应该HTTPException在验证失败时引发 an ,或者使用自定义异常处理程序,以便处理异常,如本答案ValueError的选项 2 所示。此外,还可以对参数进行额外的验证,如FastAPI 文档中所述(另请参阅类实现)。@validatorQueryQuery

作为旁注,关于定义可选参数,下面的示例使用模块中的Optional类型提示(伴随None作为默认值Querytyping;但是,您可能还想看看这个答案这个答案,它们描述了如何做到这一点的所有可用方法。

工作示例

from fastapi import FastAPI, Depends, Query, HTTPException
from pydantic import BaseModel, Field, validator
from typing import List, Optional, Literal
from enum import Enum

app = FastAPI()

class Status(str, Enum):
    new = 'New'
    old = 'Old'


class ServiceStatus(BaseModel):
    status: Optional[Status] = Field (Query(..., description='Select service status'))
    msg: Optional[str] = Field (Query(None, description='Type something'))
    choice: Literal['a', 'b', 'c', 'd'] = Field (Query(..., description='Choose something'))
    comments: List[str] = Field (Query(..., description='Add some comments'))
    
    @validator('choice')
    def check_choice(cls, v):
        if v == 'b': 
             raise HTTPException(status_code=422, detail='Wrong choice')
        return v

@app.get('/status')
def main(status: ServiceStatus = Depends()):
    return status
Run Code Online (Sandbox Code Playgroud)

更新

请注意,在 Pydantic V2 中,@validator已被弃用并被@field_validator. 请查看此答案以获取更多详细信息和示例。


归档时间:

查看次数:

6123 次

最近记录:

1 年,7 月 前