所以,让我们说我有两个数据存储模型:
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)
答案 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在他的回答中提到的那样。