GAE:当另一个实体的价值发生变化时,改变一个实体的价值

时间:2014-08-22 16:19:23

标签: python google-app-engine jinja2 google-cloud-datastore app-engine-ndb

所以,让我们说我有两个数据存储模型:

class Author(ndb.Model):
    name = ndb.StringProperty()
    has_dog = ndb.BooleanProperty(default = False)

class Book(ndb.Model):
    title = ndb.StringProperty()
    author_key = ndb.KeyProperty() # key of associated Author entity

创建 Book 实体后,会为其author_key分配作者实体的密钥。现在,我可以查询每位作者的书籍列表,如下所示:

books_per_author = Book.query(Book.author_key == author_key).fetch()

...然后在jinja模板上渲染它们:

{% for book in books_per_author %}
    <h2>{{book.title}}</h2>
{% endfor %}

但是,如果我还要在同一模板中显示作者has_dog值,该怎么办?也许我可以将数据标准化为Book实体,如下所示:

class Book(ndb.Model):
    title = ndb.StringProperty()
    author_key = ndb.KeyProperty()
    author_has_dog = ndb.BooleanProperty() # get this value from Author entity before book.put() happens

现在,当我们创建一个Book实体时,我们只需获取作者的has_dog值并将其保存在Book的author_has_dog属性中。问题解决了,我们可以这样做:

{% for book in books_per_author %}
    <h2>{{book.title}}</h2>
    <div>Has dog: {{book.author_has_dog}}</div>
{% endfor %}

问题:现在,如果我们突然更改has_dog实体中Author的值,该怎么办?我们如何有效地更改与该作者关联的许多author_has_dog实体内的Book值?

已编辑以包含NewBook处理程序:

class NewBook(BaseHandler):
    def get(self):
        title = self.request.get('title')
        author_key = self.get_author_key()
        self.render('booklist-per-author.html', title = title, author_key = author_key)

2 个答案:

答案 0 :(得分:1)

更好的选择是从书中引用作者:

{% for book in books_per_author %}
    <h2>{{book.title}}</h2>
    <div>Has dog: {{book.author_key.get().has_dog}}</div>
{% endfor %}

并且不需要更新处理。

您可能希望触发作者的预取;在视图代码中,在渲染模板之前,请调用:

book.author_key.get_async()

为了对作者对象进行异步提取,当你的模板被渲染时,它可能已经到了。

答案 1 :(得分:0)

使用pre_put function,{{3}}会在您put()作者实体时自动运行:

class Author(ndb.Model):
    name = ndb.StringProperty()
    has_dog = ndb.BooleanProperty(default = False)

    def _pre_put_hook(self):
        # update books ...
        books = Book.query(Book.author_key == author_key).fetch()
        for book in books:
            book.author_has_dog = self.has_dog
        ndb.put_multi(books)

如果作者倾向于拥有大量书籍,这不会扩展得太好,所以您可能希望卸载到定期检查不一致的cron作业,但是这样可能会使数据变得陈旧。 / p>

或者,每次都要看作者,正如Martjn在他的回答中提到的那样。