我使用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会话与您刚才所做的保持一致。