You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 20:02:52