如何在使用sqlalchemy删除父项时使childre的外键无效?

时间:2015-12-28 17:18:22

标签: python postgresql sqlalchemy

我有ParentChild模型的基本Flask应用程序:

class Parent(db.Model):
    __tablename__ = 'parents'

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


class Child(db.Model):
    __tablename__ = 'children'

    id = db.Column(db.Integer, primary_key=True)
    parent_id = db.Column(db.Integer, db.ForeignKey('parents.id'), nullable=False)
    parent = db.relationship('Parent', backref=db.backref('children', cascade='all,delete'))
    name = db.Column(db.String)

作为数据库我正在使用Postgres,如果它很重要的话。 现在我要执行以下操作:从子项中删除cascade='all,delete'并使此parent_id可以为空。即从Parent移除Childparent_id == NULLNULL保持一致。

我知道我可以使用模式创建脚本为FK添加约束来指定它。但我只想将其标记为OutputDebugStringA()并允许SqlAlchemy控制孩子的FK无效。

1 个答案:

答案 0 :(得分:6)

在文档的relevant section中详细解释了这一点。确保您还阅读“ORM级别”删除“级联与外键级别”ON DELETE“级联”部分以了解建议的解决方案之间的差异。

ORM级别

  

现在我要执行以下操作:从子项中删除cascade='all,delete'并使此parent_id可以为空。

这样做,你会得到你想要的确切行为。

class Child(db.Model):
    __tablename__ = 'children'

    id = db.Column(db.Integer, primary_key=True)
    parent_id = db.Column(db.Integer, db.ForeignKey('parents.id'), nullable=True)
    parent = db.relationship('Parent', backref=db.backref('children'))
    name = db.Column(db.String)

另请注意,allsave-update, merge, refresh-expire, expunge, delete的同义词,因此all, deleteall相同。

数据库级别

如果要在数据库级别上有ON DELETE SET NULL约束,可以在ForeighKey定义中指定ondelete='SET NULL'或不执行任何操作(因为它是外键的默认行为)。要使其在数据库级别上运行,您还需要将passive_deletes设置为True'all'(请参阅文档了解差异)。

class Child(db.Model):
    __tablename__ = 'children'

    id = db.Column(db.Integer, primary_key=True)
    parent_id = db.Column(db.Integer, db.ForeignKey('parents.id', ondelete='SET NULL'), nullable=True)
    parent = db.relationship('Parent', backref=db.backref('children', passive_deletes=True))
    name = db.Column(db.String)