如何合并SQLModel与Pydantic宠物模型并区分来源,避免冗余存储?
解决方案:在Pydantic层注入鉴别器字段,不修改数据库模型
核心思路是把鉴别器字段只放在Pydantic Schema层,不需要在SQLModel数据库模型中添加,避免数据库冗余。通过将SQLModel实例转换为对应Pydantic Schema时自动注入类型标识,实现API返回数据的类型区分。
步骤1:定义无冗余字段的SQLModel数据库模型
保持数据库模型简洁,不需要添加type这类标识字段:
from sqlmodel import SQLModel, Field class Dog(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) name: str breed: str # 狗独有的属性 class Cat(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) name: str favorite_toy: str # 猫独有的属性
步骤2:带鉴别器的Pydantic Schema设计
定义父类Schema并指定鉴别器字段,子类Schema固定type字段值,实现类型区分:
from pydantic import BaseModel from typing import Literal, Union # 父类Schema,指定鉴别器为type字段 class Pets(BaseModel): type: str name: str model_config = {"discriminator": "type"} # 狗的Schema,固定type为dog class DogSchema(Pets): type: Literal["dog"] = "dog" breed: str # 猫的Schema,固定type为cat class CatSchema(Pets): type: Literal["cat"] = "cat" favorite_toy: str
步骤3:FastAPI接口中转换并合并数据
查询数据库后,将SQLModel实例转换为对应Pydantic Schema(自动带上type字段),再合并返回:
from fastapi import FastAPI from sqlmodel import Session, create_engine, select engine = create_engine("sqlite:///pets.db") app = FastAPI() @app.get("/pets", response_model=list[Union[DogSchema, CatSchema]]) def get_all_pets(): with Session(engine) as session: # 查询所有狗和猫 dogs = session.exec(select(Dog)).all() cats = session.exec(select(Cat)).all() # 转换为对应的Pydantic Schema,自动注入type字段 dog_schemas = [DogSchema.from_orm(dog) for dog in dogs] cat_schemas = [CatSchema.from_orm(cat) for cat in cats] # 合并后返回 return dog_schemas + cat_schemas
方案优势
- 无数据库冗余:鉴别器字段仅存在于API返回的序列化数据中,不影响数据库表结构。
- 类型安全:通过
Literal固定类型值,避免手动赋值错误;FastAPI会自动校验返回数据的类型。 - 友好的API文档:FastAPI会基于鉴别器生成清晰的OpenAPI文档,前端可以根据
type字段轻松区分宠物类型。
内容的提问来源于stack exchange,提问作者ikreb
相关产品推荐
相关产品推荐

