SQLAlchemy—当父类已经持久化时,如何插入join Table Inherited类实例



我使用SQLAlchemy join 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 实例并手动为其分配一个现有的id到FK列并将其发送到数据库时。我得到一个IntegrityError(重复唯一约束违反),因为SQLAlchemy试图在数据库中创建一个新的父条目,并将id传递给子实例。

所以,真正的问题是:

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

您可以通过使用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=...)
)

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

最新更新