SQLAlchemy - 如何在父级已经持久化时插入连接表继承类实例

mis*_*iso 6 python sqlalchemy flask flask-sqlalchemy

我使用 SQLAlchemy Joined Table Inheritance声明了两个类。另外我正在使用Flask-SQLAlchemy和 Flask。

class Parent(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    type = db.Column(db.String(50))

    __mapper_args__ = {
        'polymorphic_identity': 'parent',
        'polymorphic_on': type
    }


class Child(Parent):

    id = db.Column(db.Integer, db.ForeignKey('parent.id'), primary_key=True)
    brand_id = db.Column(db.Integer, nullable=False)

    __mapper_args__ = {
        'polymorphic_identity': 'child',
    }
Run Code Online (Sandbox Code Playgroud)

父子表之间是一对一的关系,在子端可选出现。

当我创建 Child 的新实例,将其添加到会话并将其提交到数据库时,一切都按预期工作。SQLAlchemy 向INSERT父表发送一条语句,然后INSERT向子表发送另一条语句,全部由其自身完成,避免任何外键约束违规。

在应用程序的某个点,我想在子表中添加一个新行,引用父表中已经存在的行。

当我创建一个新Child实例并手动为其分配一个现有的 id 到 FK 列并将其发送到数据库时。我收到一个 IntegrityError(重复唯一约束冲突),因为 SQLAlchemy 尝试在数据库中创建一个新的父条目,并将 id 传递给子实例。

所以,真正的问题是:

我如何告诉 Sqlalchemy,父条目已经存在于数据库中,而我只想创建子条目?

Cox*_*oxy 1

您可以通过使用 SQLALchemy Core 直接向子项进行插入来解决此问题,而不是使用 ORM 添加它。

# where obj is some instance of your parent and session some sqlalchemy session
obj.type = 'child'
session.execute(
  sa.insert(Child.__table__).values(id=obj.id, brand_id=...)
)
Run Code Online (Sandbox Code Playgroud)

因为这是在 orm 之外,所以您现在可能需要从会话中删除原始父对象,以便 SQLAlchemy ORM 会话与您刚刚执行的操作保持同步。