如何在 FastAPI 中使用 Pydantic 模型定义查询参数?
- 2025-02-20 09:24:00
- admin 原创
- 79
问题描述:
我正在尝试建立一个像这样的端点/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.....
结果是我收到一个似乎与此问题相关的错误
错误说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.....
它正在工作(我不明白为什么) - 但问题是如何以及在哪里添加描述和标题?
解决方案 1:
要创建 Pydantic 模型并使用它来定义查询参数,您需要Depends()
在端点中使用 和 参数。要将description
、title
等添加到查询参数,您可以将 包装Query()
在 中Field()
。
还应注意,可以使用Literal
类型而不是,如此处和此处Enum
所述。此外,如果想要在 Pydantic 模型中定义一个字段并将其用作查询参数,他们要么需要在单独的依赖项类中实现它,如此处和此处所示,要么再次将包装在中,如下所示。List
`Query()`Field()
此外,要在 Pydnatic 模型中对查询参数执行验证,可以像往常一样使用 Pydantic 的 执行此操作,如此处 以及此处和此处@validator
所示。请注意,在这种情况下,当用于查询参数 时,引发将导致。因此,您应该在验证失败时引发,或者使用自定义异常处理程序来处理异常,如此答案的选项 2 所示。此外,还可以对参数进行其他验证,如FastAPI 文档中所述(另请参阅类实现)。BaseModel
`ValueErrorInternal Server Error
HTTPExceptionValueError
@validatorQuery
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(None, 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
更新 1 (关于@validator
)
请注意,在 Pydantic V2 中,@validator
已被弃用并被替换@field_validator
。请查看此答案以获取更多详细信息和示例。
更新2(关于Query
参数)
从FastAPI 0.115.0开始,可以使用 Pydantic 模型通过以下方式声明Query
(以及Header
和)参数:Cookie
from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
return filter_query
扫码咨询,免费领取项目管理大礼包!