当使用具有不同设置的更复杂的分层模型时,如何处理级联删除时,很难事先弄清楚 adelete()
究竟会对数据库做什么。
我找不到任何方法从 SQLAlchemy 中获取这条信息(“嘿,SQLAlchemy,如果我在那边删除那个对象会删除什么? ”)。自己实现这一点似乎并不是一个选择,因为这迟早会在我的预测和实际后果delete()
不同的情况下导致,这会让用户非常……不愉快。
当使用具有不同设置的更复杂的分层模型时,如何处理级联删除时,很难事先弄清楚 adelete()
究竟会对数据库做什么。
我找不到任何方法从 SQLAlchemy 中获取这条信息(“嘿,SQLAlchemy,如果我在那边删除那个对象会删除什么? ”)。自己实现这一点似乎并不是一个选择,因为这迟早会在我的预测和实际后果delete()
不同的情况下导致,这会让用户非常……不愉快。
我在 SQLAlchemy 邮件列表上问了这个问题
,Michael Bayer 解释了可能的选项(再次感谢!:-):
在刷新之前 session.deleted 中不存在的唯一删除是因为特定对象是“孤儿”而发生的删除,以及由于该孤儿的级联而将被删除的对象。
因此,在不考虑孤儿的情况下, session.deleted 会告诉您要删除的所有内容。
要将孤儿考虑在内,需要像工作单元一样遍历所有关系,查找当前是孤儿的对象(有一个 API 函数会告诉您这一点 - 如果该对象被任何引用的属性视为“孤儿”对它使用 delete-orphan 级联,它被认为是“孤儿”),然后遍历这些孤儿的关系,认为它们被标记为“已删除”,然后对那些新删除的对象再次执行所有规则。
现在的系统是由 orm/dependency.py 实现的。在会话中正常运行一个工作单元进程可能并不难,但只是不发出 SQL,这将为您提供最终的刷新计划。但这是一个昂贵的过程,我不想一直调用它。
在这里添加功能很困难,因为用例不清楚。知道什么将被删除基本上需要实际进行一半的刷新过程。但是您已经可以在刷新过程本身内部实现事件,最直接的是 before_delete() 和 after_delete() 事件,它们将保证捕获所有内容。因此,在您无论如何都进行刷新并且可以将事件放入其中之前,基本上运行一半刷新的新功能的基本原理尚不清楚。
我想最大的问题是,“你什么时候打电话给这个”。
一个简单的系统是添加一个新事件“flush_plan_complete”,这将使您在完整计划已组装但在任何 SQL 发生之前进入flush()。它可以允许您为活动注册更多对象,然后它会重新运行刷新计划以考虑任何新更改(因为无论如何它现在都是这样工作的)。这种注册将如何进行是很棘手的,因为在那里正常使用 Session 会很好,但这使得实现起来更加复杂。但随后它可以再次迭代新的更改,并在正常继续之前找到要采取的任何剩余步骤。