FastAPI:修改ICategoryRead Schema使分类输出为枚举值数组
问题描述
我定义了如下枚举类:
from enum import Enum class CategoryEnum(str, Enum): A = "A" B = "B"
同时定义了两个SQLModel数据表:
from app.enums import CategoryEnum from sqlmodel import SQLModel, Field, Relationship from typing import Optional, List if TYPE_CHECKING: from app.models.project_model import Project class Category(SQLModel, table=True): __table_name__ = 'category' id: Optional[int] = Field( primary_key=True, index=True, nullable=False, ) category: str project_id: Optional[int] = Field( default=None, foreign_key='project.id', nullable=False) class Project(SQLModel, table=True): __table_name__ = 'project' id: Optional[int] = Field( primary_key=True, index=True, nullable=False, ) categories: List[Category] = Relationship( back_populates='project', sa_relationship_kwargs={ "lazy": "selectin", 'cascade': 'all,delete,delete-orphan', "primaryjoin": "category.project_id==project.id", })
当前使用的Pydantic读取Schema如下:
from pydantic import BaseModel from typing import List class ICategoryRead(BaseModel): category: CategoryEnum class IProjectRead(BaseModel): categories: List[ICategoryRead]
在FastAPI中查询Project记录时,categories字段的输出格式是:
"categories": [ { "category": "A" }, { "category": "B" } ],
请问如何修改ICategoryRead Schema,让categories字段输出变为:
"categories": ["A", "B"],
解决方案
你可以通过以下几种方式实现需求:
方法一:直接在IProjectRead中转换字段格式
不需要保留单独的ICategoryRead,直接在IProjectRead里通过字段验证器提取枚举值:
from pydantic import BaseModel, field_validator from typing import List class IProjectRead(BaseModel): categories: List[Category] @field_validator('categories', mode='before') def extract_category_values(cls, value): return [item.category for item in value] class Config: orm_mode = True # 确保能正确解析SQLModel实例
方法二:用Pydantic序列化器简化处理
使用PlainSerializer直接指定字段的序列化逻辑,代码更简洁:
from pydantic import BaseModel, PlainSerializer from typing import List class IProjectRead(BaseModel): categories: List[CategoryEnum] = PlainSerializer( lambda cats: [cat.category for cat in cats], return_type=List[str] ) class Config: orm_mode = True
方法三:修改ICategoryRead为单值类型
如果需要保留ICategoryRead,可以将其定义为直接返回枚举值的类型,再配合List使用:
from pydantic import BaseModel from typing import List class ICategoryRead(BaseModel): category: CategoryEnum class Config: json_encoders = { CategoryEnum: lambda v: v.value } orm_mode = True # 此时IProjectRead可以直接使用List[ICategoryRead],但需要额外处理列表结构 # 更高效的方式是直接在IProjectRead中映射成数组: class IProjectRead(BaseModel): categories: List[str] @field_validator('categories', mode='before') def map_categories(cls, value): return [ICategoryRead.from_orm(item).category for item in value]
以上方案中,方法二的代码最简洁且性能最优,修改后FastAPI返回的categories字段会直接输出["A", "B"]的数组格式。
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

