SQLAlchemy向已有父类添加子类触发KeyError问题求助
问题根源分析
- 查询结果处理错误:
session.execute(query)返回的是Result对象,调用first()得到的是Row实例而非UserBase对象。直接访问parent.my_cards会触发KeyError,因为Row仅支持按列名索引,不具备模型类的属性。 - 关联关系定义不完整:
UserBase的my_cards关系未指定反向关联,AssociationClass也缺少与UserBase的关联字段,导致ORM无法正确映射双向关系。
修复步骤
1. 补全数据库模型的关联定义
修改database_models.py,完善双向关联:
class UserBase(Base): """ An account for storing and accessing multiple learning cards """ __tablename__ = 'users' id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) telegram_id: Mapped[str] = mapped_column(String, unique=True) username: Mapped[str] = mapped_column(String(100), unique=True) name: Mapped[str] = mapped_column(String(200)) surname: Mapped[str] = mapped_column(String(200)) # 关联到AssociationClass的user字段 my_cards: Mapped[list['AssociationClass']] = relationship(back_populates="user") class AssociationClass(Base): __tablename__ = 'association_table' user_id: Mapped[int] = mapped_column(ForeignKey('users.id'), primary_key=True) card_id: Mapped[int] = mapped_column(ForeignKey('cards.id'), primary_key=True) # 添加与UserBase的反向关联 user: Mapped['UserBase'] = relationship(back_populates="my_cards") card: Mapped['CardBase'] = relationship()
2. 修正查询结果的处理逻辑
在add_child_to_db函数中,直接获取模型实例而非Row对象:
async def add_child_to_db( query, child, my_async_session: AsyncSession): """ Adds a child class to parent class """ async with my_async_session.begin(): try: # 用scalar()直接获取单个UserBase实例 parent = await my_async_session.scalar(query) if not parent: raise ValueError("目标用户不存在") a = AssociationClass() a.card = child parent.my_cards.append(a) except SQLAlchemyError as exc: print(exc) raise
额外注意事项
- 无需在
async with session.begin()上下文内手动调用await session.close(),上下文管理器会自动处理会话生命周期。 - 若查询可能返回多个结果,改用
await my_async_session.scalars(query).first()获取目标实例。 - 修改模型后,需重新生成数据库表(或通过迁移工具执行表结构更新),确保关联字段生效。
内容的提问来源于stack exchange,提问作者Ani
相关产品推荐
相关产品推荐

