我正在使用带有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中获得这种行为?
答案 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中,这是没用的。