谷歌应用引擎中的递归删除

时间:2009-06-28 12:48:37

标签: python django 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级深度,我希望有一种方法可以确保自动完成。

我发现这个article关于它如何与Java一起工作,这似乎也是我想要的。

任何人都知道如何在django中获得这种行为?

4 个答案:

答案 0 :(得分:6)

您需要手动实现此操作,方法是查找受影响的记录并在删除父记录的同时删除它们。如果您愿意,可以通过覆盖父类的.delete()方法来自动删除所有相关记录。

出于性能原因,您几乎肯定希望使用仅限密钥的查询(允许您删除实体的密钥而无需获取和解码实际实体)和批量删除。例如:

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

答案 1 :(得分:2)

实际上,这种行为是针对GAE的。 Django的ORM在.delete()上模拟“ON DELETE CASCADE”。

我知道这不是你问题的答案,但也许它可以帮助你找错地方。

答案 2 :(得分: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]

然后查询ancestor = top将查找所有级别的所有记录。因此删除它们很容易。

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

答案 3 :(得分:1)

如果您的层次结构只有少量级别,那么您可以使用看起来像文件路径的字段执行某些操作:

daddy.ancestry = "greatgranddaddy/granddaddy/daddy/"
me.ancestry = daddy.ancestry + me.uniquename + "/"
有点像。你确实需要独特的名字,至少在兄弟姐妹中是独一无二的。

对象ID中的路径已经这样做,但IIRC与实体组绑定,建议您不要用它来表达数据域中的关系。

然后你可以构造一个查询来使用初始子字符串技巧返回所有granddaddy的后代,如下所示:

query = Person.all()
query.filter("ancestry >", gdaddy.ancestry + "\U0001")
query.filter("ancestry <", gdaddy.ancestry + "\UFFFF")

显然,如果你不能将祖先放入500字节的StringProperty中,这是没用的。