SQLAlchemy 调用 before_update 但不是 after_delete

2 投票
1 回答
595 浏览
提问于 2025-04-18 03:36

有人能告诉我我哪里做错了吗?

我有一个方法用来注册事件(比如在更新之前、删除之后、插入之前等)链接

@classmethod
def register_tree(cls):
    event.listen(cls, "before_insert", cls.mptt_before_insert)
    event.listen(cls, "after_delete", cls.mptt_after_delete)
    event.listen(cls, "before_update", cls.mptt_before_update)

当我注册了事件并尝试删除一行数据时(链接)。

class Tree(Base, BaseNestedSets):
    __tablename__ = "tree"

    id = Column(Integer, primary_key=True)

Tree.register_tree()

def test_delete_node(self):
    node = self.session.query(Tree).filter(Tree.id == 4).one()
    self.session.delete(node)
    # id lft rgt lvl parent tree
    self.assertEqual([(1, 1, 16, 1, None, 1),
                      (2, 2, 5, 2, 1, 1),
                      (3, 3, 4, 3, 2, 1),
                      (7, 6, 15, 2, 1, 1),
                      (8, 7, 10, 3, 7, 1),
                      (9, 8, 9, 4, 8, 1),
                      (10, 11, 14, 3, 7, 1),
                      (11, 12, 13, 4, 10, 1)], self.result.all())

结果调用了更新之前的方法,而不是删除之后的方法。但是如果我把更新之前的事件注释掉(链接),它就能正常工作。

@classmethod
def register_tree(cls):
    event.listen(cls, "before_insert", cls.mptt_before_insert)
    event.listen(cls, "after_delete", cls.mptt_after_delete)
    # event.listen(cls, "before_update", cls.mptt_before_update) <-- IF comment this, called after_delete method. It's OK.

构建状态 链接

到底出什么问题了?

1 个回答

1

在这里解决这个问题 https://groups.google.com/forum/#!msg/sqlalchemy/gdwuMjNfrPc/v2ChQjGjWwoJ

结果发现,当删除一个有孩子节点的节点时,sqlalchemy 默认会先把孩子节点的父节点设置为 None(也就是没有父节点),然后再删除这个节点。如果我设置了 cascade="all,delete",那么它会一个一个地删除节点,而不是先更新再删除。

撰写回答