Python googleappengine中的递归删除

Python googleappengine中的递归删除,python,django,google-app-engine,Python,Django,Google App Engine,我正在将google应用程序引擎与django 1.0.2(以及django助手)一起使用,我想知道人们是如何进行递归删除的。 假设您有一个类似这样的模型: class Top(BaseModel): pass class Bottom(BaseModel): daddy = db.ReferenceProperty(Top) query = Person.all() query.filter("ancestry >", gdaddy.ancestry + "\U0001

我正在将google应用程序引擎与django 1.0.2(以及django助手)一起使用,我想知道人们是如何进行递归删除的。 假设您有一个类似这样的模型:

class Top(BaseModel): pass class Bottom(BaseModel): daddy = db.ReferenceProperty(Top)
query = Person.all()
query.filter("ancestry >", gdaddy.ancestry + "\U0001")
query.filter("ancestry <", gdaddy.ancestry + "\UFFFF")
顶级(基本型号): 通过 类底部(基本模型): daddy=db.ReferenceProperty(顶部) 现在,当我删除“Top”类型的对象时,我希望所有相关的“Bottom”对象也被删除

现在的情况是,当我删除一个“顶部”对象时,“底部”对象会保留下来,然后我会得到不属于任何地方的数据。在视图中访问数据存储时,我最终得到:

Caught an exception while rendering: ReferenceProperty failed to be resolved. 呈现时捕获到异常:无法解析ReferenceProperty。 我当然可以找到所有对象并删除它们,但由于我的真实模型至少有5层深,我希望有一种方法可以确保这可以自动完成

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


有人知道我如何在django中也能得到这种行为吗?

事实上,这种行为是GAE特有的。Django的ORM在.DELETE()上模拟“ON DELETE CASCADE”


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

如果你的层次结构只有少量的层次,那么你可能可以使用一个看起来像文件路径的字段:

daddy.ancestry = "greatgranddaddy/granddaddy/daddy/"
me.ancestry = daddy.ancestry + me.uniquename + "/"
有点像。您确实需要唯一的名称,至少在兄弟姐妹之间是唯一的

对象ID中的路径已经在某种程度上实现了这一点,但是IIRC与实体组绑定在一起,建议不要使用实体组来表示数据域中的关系

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

class Top(BaseModel): pass class Bottom(BaseModel): daddy = db.ReferenceProperty(Top)
query = Person.all()
query.filter("ancestry >", gdaddy.ancestry + "\U0001")
query.filter("ancestry <", gdaddy.ancestry + "\UFFFF")
query=Person.all()
query.filter(“祖先>”,gdaddy.escentry+“\U0001”)

query.filter(“祖先您需要手动实现这一点,方法是查找受影响的记录,并在删除父记录的同时将其删除。如果愿意,您可以通过覆盖父类上的.delete()方法来简化此过程,以自动删除所有相关记录

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

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

重新考虑数据结构。如果关系在记录生存期内永远不会改变,则可以使用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]
然后查询祖先=top将找到所有级别的所有记录。因此,删除它们将很容易

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

出于兴趣,db.delete会对每个实体调用delete()吗?它经过了严格的优化,所以我有点怀疑你不能将这两个技巧结合起来。不过,仅对key_有好处。不,db.delete()直接对应于一个RPC,它并行发送所有要删除的键。entity.delete()只是调用db.delete(self)的语法糖。是的,它会-尽管db.delete(top.bottom_set.fetch(1000))会更快(假设实体少于1000个)。我无法实现这一点,但这个答案已经有将近4年的历史了,所以可能就是这样。GAE是否仍然支持按键查询(jgeewax的解决方案运行良好)?我已经搜索过了,但不清楚。很漂亮。列表理解的使用很好。我第一次看到其中一个有两个循环!但是看起来它们的顺序是另一个,外部循环是第一个。