【问题标题】:SQLAlchemy - How to insert a Joined Table Inherited class instance when the parent is already persistedSQLAlchemy - 当父级已经持久化时如何插入连接表继承类实例
【发布时间】:2017-02-17 00:36:27
【问题描述】:

我使用 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',
    }

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

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

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

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

所以,真正的问题是:

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

【问题讨论】:

  • 如果它是一对一的,孩子是可选的,它不适合继承场景。常规关系可能更适合这种情况。
  • 您应该在child 中添加与parent 的关系()。然后不设置FK,而是设置child.parent = ParentObj [the instance of the parent]。

标签: python flask sqlalchemy flask-sqlalchemy


【解决方案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=...)
)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 2012-07-13
    相关资源
    最近更新 更多