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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 05:13:28