Sqlalchemy 在数据库有机会评估外键约束之前将子行清空。如果您添加passive_deletes=True
到关系中,sqlalchemy将不会尝试管理相关实体的删除,而只是让数据库根据您的配置方式来做这件事。在删除父级之前不会先发出选择来填充关系。设置为True
仍会导致会话中的子对象将其 FK 列设置为NULL
。
这个配置:
class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
parent_id = db.Column(db.Integer, db.ForeignKey('person.id', ondelete='RESTRICT'))
parent = db.relationship('Person', remote_side=[id], back_populates='children')
children = db.relationship('Person', back_populates='parent', passive_deletes=True)
if __name__ == '__main__':
with app.app_context():
db.drop_all()
db.create_all()
parent = Person()
db.session.add(parent)
child = Person(parent=parent)
db.session.commit()
db.session.delete(parent)
db.session.commit()
提高:
sqlalchemy.exc.IntegrityError:(mysql.connector.errors.IntegrityError)1451(23000):无法删除或更新父行:外键约束失败(test
. person
,CONSTRAINT person_ibfk_1
FOREIGN KEY(parent_id
)REFERENCES person
(id
))
if __name__ == '__main__':
with app.app_context():
db.drop_all()
db.create_all()
parent = Person()
db.session.add(parent)
child = Person(parent=parent)
db.session.commit()
db.session.query(Person).all() # reload the people into the session before deleting parent
db.session.delete(parent)
db.session.commit()
parent_id
... 仍然会将孩子的字段设为空,即使使用passive_deletes=True
. passive_deletes='all'
走的路也是如此。