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

Fast API嵌套Schema处理及数据存储报错问题排查

问题分析与解决方案

错误原因

你的Book SQLAlchemy模型仅定义了publisher_id外键字段和publishers关系属性,没有名为publisher的字段,但你将包含嵌套publisher对象的请求数据直接解构传入Book构造函数,导致触发TypeError: 'publisher' is an invalid keyword argument for Book错误。

另外注意你的CRUD代码里有笔误:obj_in_data = jsonable_encoder(obj_in_data)应该改为obj_in_data = jsonable_encoder(obj_in),否则会引用未定义的变量。

解决方案

方案1:手动移除无效字段

在构造Book对象前,从序列化后的字典中删除publisher键:

class CRUDBook(CRUDBase[Book, BookCreate, BookUpdate]):
    def create_with_owner(
        self, db: Session, *, obj_in: BookCreate, owner_id: int
    ) -> Book:
        # 检查并创建publisher(原代码逻辑保留)
        publisher = crud.publisher.show(db=db, name=obj_in.publisher.name)
        if not publisher:
            publisher = crud.publisher.create(
                db=db, obj_in=PublisherCreate(name=obj_in.publisher.name)
            )

        # 修正笔误,序列化请求数据
        obj_in_data = jsonable_encoder(obj_in)
        # 移除Book模型不接受的publisher字段
        del obj_in_data["publisher"]
        
        db_obj = self.model(
            **obj_in_data,
            owner_id=owner_id,
            publisher_id=publisher.id,
        )
        db.add(db_obj)
        db.commit()
        db.refresh(db_obj)
        return db_obj

方案2:利用Pydantic的字段排除功能

直接通过Pydantic的dict()方法或jsonable_encoder的exclude参数过滤掉publisher字段,更简洁:

class CRUDBook(CRUDBase[Book, BookCreate, BookUpdate]):
    def create_with_owner(
        self, db: Session, *, obj_in: BookCreate, owner_id: int
    ) -> Book:
        publisher = crud.publisher.show(db=db, name=obj_in.publisher.name)
        if not publisher:
            publisher = crud.publisher.create(
                db=db, obj_in=PublisherCreate(name=obj_in.publisher.name)
            )

        # 方式1:用dict方法排除publisher
        obj_in_data = obj_in.dict(exclude={"publisher"})
        # 方式2:或用jsonable_encoder带exclude参数
        # obj_in_data = jsonable_encoder(obj_in, exclude={"publisher"})
        
        db_obj = self.model(
            **obj_in_data,
            owner_id=owner_id,
            publisher_id=publisher.id,
        )
        db.add(db_obj)
        db.commit()
        db.refresh(db_obj)
        return db_obj

优化建议:统一关系字段命名

你的Book模型中关系字段命名为publishers(复数),但业务逻辑里一个书籍对应一个出版商,建议改为单数publisher,避免语义混淆:

# 修改Book模型的关系定义
class Book(Base):
    # ... 其他字段保持不变
    publisher_id = Column(Integer, ForeignKey("publisher.id"))
    publisher = relationship("Publisher", back_populates="books")  # 改为单数

# 对应修改Publisher模型的back_populates
class Publisher(Base):
    # ... 其他字段保持不变
    books = relationship("Book", back_populates="publisher")

内容的提问来源于stack exchange,提问作者Olaw2jr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 21:30:41