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

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

我试图有一个像

/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.....

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

错误提示

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


然后我找到了另一个解释的解决方案here

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

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.....

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

python fastapi openapi pydantic
1个回答
12
投票

要创建 Pydantic 模型并使用它来定义查询参数,您需要将

Depends()
与端点中的参数一起使用。要添加
description
title
等来查询参数,您可以将
Query()
包装在
Field()
中。

还应该注意的是,可以使用

Literal
类型代替
Enum
,如herehere所述。此外,如果想在 Pydantic 模型中定义
List
字段并将其用作查询参数,他们要么需要在单独的依赖类中实现此功能,如 herehere 所示,或者再次将
Query()
包裹在
Field()
中,如下所示。

此外,要对 Pydnatic 模型内的查询参数进行验证,可以像往常一样使用 Pydantic 的

@validator
来执行此操作,如 hereherehere 所示。 注意,在这种情况下,
BaseModel
用于查询参数,提高
ValueError
将导致
Internal Server Error
。因此,您应该在验证失败时引发
HTTPException
,或者使用自定义异常处理程序,以处理
ValueError
异常,如 this answer 的选项 2 所示。除了
@validator
之外,还可以对
Query
参数进行额外验证,如 FastAPI 文档 中所述(另请参阅
Query
类实现
)。

作为旁注,关于定义可选参数,下面的示例使用

Optional
模块中的
None
 类型提示(伴随 Query
 作为 
typing
中的默认值);但是,您可能还想查看这个答案这个答案,它们描述了如何做到这一点的所有可用方法。

工作示例

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

更新

请注意,在 Pydantic V2 中,

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

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