python - SQLAlchemy FK ondelete 不限制
问题描述
我建立了自我参照关系。一个人可以有一个单亲(或无),一个人可以有多个孩子(或无)。
因此允许NULL作为 FK:
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')
但是,如果 Person 是父母,我想禁止删除他们。所以我包含了该ondelete='RESTRICT'
子句,但它没有效果。parent_id 列在删除父级时仍设置为 NULL。
(注意我的 SQLite 连接已将 pragma 外键约束设置为 ON)
为什么删除父级时数据库不会抛出错误,因此以它作为外键的子列会限制这一点?
解决方案
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
,CONSTRAINTperson_ibfk_1
FOREIGN KEY(parent_id
)REFERENCESperson
(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'
走的路也是如此。
推荐阅读
- arrays - 无法访问方括号下的json数据-nodejs
- mysql - MySQL平均函数未返回预期结果
- javascript - 为什么我的 React 组件在按 useState() 控制的值进行过滤时显示不正确的数据?
- javascript - 计算字符串中的括号
- node.js - 如何使用 sequelize ORM 在 postgres 中定义外键约束?
- javascript - 开玩笑模拟“点击”的作品古怪而测试失败
- dart - 如何为字段的注释生成 Dart 代码?
- c# - 如何将值从 Form 传递到 UserControl?
- sql - SQL Server:为同一年的记录创建增量计数器?
- python - 所有模块导入失败 - 使用 python 和树莓派