如何删除连接到通过appengine中的Key属性连接的实体的所有实体

时间:2017-08-06 13:07:47

标签: python python-2.7 google-app-engine

我有以下数据存储模型。

class UserDetail(ndb.Model):
    name=ndb.StringProperty(required=True)
    password=ndb.StringProperty(required=True)
    email=ndb.StringProperty(required=False)
    posts=ndb.KeyProperty(kind='Post',repeated=True)

class Post(ndb.Model):
    subject=ndb.StringProperty(required=True)
    content=ndb.TextProperty(required=True)
    created=ndb.DateTimeProperty(auto_now_add=True)
    user=ndb.KeyProperty(kind='UserDetail')
    comments=ndb.KeyProperty(kind='Comment',repeated=True)

class Comment(ndb.Model):
    body=ndb.StringProperty(required=True)
    user=ndb.KeyProperty(kind='UserDetail')
    post=ndb.KeyProperty(kind='Post')

基本上我想要删除一个帖子。当我删除帖子时,它的所有评论都应该被删除,帖子也应该从UserDetail模型的用户帖子列表中删除。我知道删除的方式是删除帖子并使用给定的帖子ID搜索评论模型并删除所有帖子并以同样的方式转到用户的帖子列表并删除所需的帖子。 有没有更好的方法呢。

1 个答案:

答案 0 :(得分:2)

最好的方法是定义pre_delete_hook。这是在删除实体之前运行的函数。让这个函数本身删除任何引用这篇文章的评论。您也可以让它从UserDetails中删除键值。代码将是这样的:

class Post(ndb.Model):
    ...
    @classmethod
    def _pre_delete_hook(cls, key):
        comments = Comment.query(Comment.post==key).fetch(keys_only=True)
        ndb.delete_multi(comments)

        details = UserDetail.query(UserDetail.posts.IN([key])).fetch()
        for detail in details:
            detail.posts.remove(key)
        ndb.put_multi(details)

您应该使用挂钩的原因是,无论代码的哪一部分尝试删除Post,您都可以保证执行所需的功能。这是一种补偿您没有使用关系数据库这一事实的方法。

您可以在documentation中找到有关挂钩的更多详细信息。我希望有所帮助!