Google App Engine中的递归删除

6 投票
4 回答
2226 浏览
提问于 2025-04-15 12:32

我正在使用 Google App Engine 和 Django 1.0.2(还有 django-helper),想知道大家是怎么处理递归删除的。

假设你有一个模型,大概是这样的:

class Top(BaseModel):
    pass

class Bottom(BaseModel):
    daddy = db.ReferenceProperty(Top)

现在,当我删除一个类型为 'Top' 的对象时,我希望所有关联的 'Bottom' 对象也能被删除。

目前的情况是,当我删除一个 'Top' 对象时,'Bottom' 对象却留在那儿,这样就会出现一些无处归属的数据。在查看数据存储时,我最终得到的是:

Caught an exception while rendering: ReferenceProperty failed to be resolved.

当然,我可以找到所有对象并逐个删除,但因为我的真实模型至少有 5 层深,所以我希望能有一种方法可以自动完成这个操作。

我找到了一篇关于 Java 的 文章,看起来这正是我想要的功能。

有没有人知道我怎么才能在 Django 中实现这种行为呢?

4 个回答

2

重新考虑一下数据结构。如果在记录的整个生命周期内,关系是不会改变的,你可以使用GAE的“祖先”功能:

class Top(db.Model): pass
class Middle(db.Model): pass
class Bottom(db.Model): pass

top = Top()
middles = [Middle(parent=top) for i in range(0,10)]
bottoms = [Bottom(parent=middle) for i in range(0,10) for middle in middles]

这样查询祖先=顶级时,就能找到所有层级的记录。所以删除它们会变得很简单。

descendants = list(db.Query().ancestor(top))
# should return [top] + middles + bottoms
2

其实这个行为是特定于GAE的。Django的ORM在执行.delete()时会模拟“删除时级联”的效果。

我知道这不是对你问题的直接回答,但也许可以帮助你避免去错误的地方寻找答案。

6

你需要手动实现这个功能,也就是说在删除父记录的同时,要查找并删除相关的记录。如果你想简化这个过程,可以在父类中重写 .delete() 方法,这样就能自动删除所有相关的记录。

为了提高性能,你几乎肯定需要使用只查询键的方式(这样可以直接获取要删除的实体的键,而不需要先获取和解码实际的实体),并且可以进行批量删除。比如:

db.delete(Bottom.all(keys_only=True).filter("daddy =", top).fetch(1000))

撰写回答