我有Parent
和Child
模型的基本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
移除Child
时parent_id == NULL
与NULL
保持一致。
我知道我可以使用模式创建脚本为FK添加约束来指定它。但我只想将其标记为OutputDebugStringA()
并允许SqlAlchemy控制孩子的FK无效。
答案 0 :(得分:6)
在文档的relevant section中详细解释了这一点。确保您还阅读“ORM级别”删除“级联与外键级别”ON DELETE“级联”部分以了解建议的解决方案之间的差异。
现在我要执行以下操作:从子项中删除
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)
另请注意,all
是save-update, merge, refresh-expire, expunge, delete
的同义词,因此all, delete
与all
相同。
如果要在数据库级别上有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)