如何在FastAPI端点中添加第二个Pydantic模型或按参数切换
解决方案
1. 拆分Pydantic模型
创建两个针对性的模型,复用基础字段减少重复代码,分别对应带date和不带date的返回结构:
from pydantic import BaseModel from datetime import date from typing import Optional, List, Union class ClicksBase(BaseModel): unit: str color: int bw: int class Config: orm_mode = True # 带date字段的模型,用于details='all'场景 class ClicksWithDate(ClicksBase): date: Optional[date] # 不带date字段的模型,用于无参数场景 class ClicksWithoutDate(ClicksBase): pass
2. 修改FastAPI端点
将响应模型声明为两种列表类型的Union,根据请求参数返回对应模型的实例:
from fastapi import HTTPException, status, Depends from sqlalchemy.orm import Session from sqlalchemy.exc import NoResultFound @xeikon_api.get('/xeikon/clicks/', response_model=Union[List[ClicksWithDate], List[ClicksWithoutDate]]) async def xeikon_Clicks_data(details: Optional[str]=None, db: Session = Depends(get_db)): """ endpoint: list all Clicks data """ try: clicks = db.query(Clicks).all() if details == 'all': return [ClicksWithDate.from_orm(click) for click in clicks] # 无参数时自动排除date字段 return [ClicksWithoutDate.from_orm(click) for click in clicks] except NoResultFound as n: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=str(n.orig.args), ) from n
关键说明
- 用
from_orm方法将ORM对象转换为Pydantic模型实例,保证序列化逻辑统一 - 无参数场景使用
ClicksWithoutDate模型,会完全排除date字段,不会返回null值 - 响应模型用
Union声明后,FastAPI会自动生成包含两种返回格式的OpenAPI文档
替代方案:动态排除字段
如果不想创建多个模型,也可以在返回时动态指定排除字段:
@xeikon_api.get('/xeikon/clicks/') async def xeikon_Clicks_data(details: Optional[str]=None, db: Session = Depends(get_db)): try: clicks = db.query(Clicks).all() if details == 'all': return [Clicks.from_orm(click).dict() for click in clicks] # 无参数时直接排除date字段 return [Clicks.from_orm(click).dict(exclude={"date"}) for click in clicks] except NoResultFound as n: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=str(n.orig.args), ) from n
这种方式无需额外模型,但OpenAPI文档只会显示包含date的结构,文档完整性不如多模型方案。
内容的提问来源于stack exchange,提问作者pawelprzegon
相关产品推荐
相关产品推荐

