Google app engine Google应用程序引擎:查询没有URL参数的实体

Google app engine Google应用程序引擎:查询没有URL参数的实体,google-app-engine,data-modeling,jinja2,app-engine-ndb,webapp2,Google App Engine,Data Modeling,Jinja2,App Engine Ndb,Webapp2,以下是我的数据模型: BlogPost(ndb.Model): title = ndb.StringProperty() body = ndb.TextProperty() author_key = ndb.KeyProperty() Author(ndb.Model): name = ndb.StringProperty() fav_colour = ndb.StringProperty() 我目前在我的主页(“/”),我想: 查询所有BlogP

以下是我的数据模型:

BlogPost(ndb.Model):
    title = ndb.StringProperty()
    body = ndb.TextProperty()
    author_key = ndb.KeyProperty() 

Author(ndb.Model):
    name = ndb.StringProperty()
    fav_colour = ndb.StringProperty()
我目前在我的主页(“/”),我想:

  • 查询所有BlogPost实体的列表,以及
  • 在BlogPost实体旁边显示其各自作者的查询
我可以像这样简单地查询所有博客帖子:

class BlogPostHandler(webapp2.RequestHandler): 
    def get(self):
        posts = BlogPost.query().fetch()
        self.render('index.html', posts = posts) #renders in Jinja2 template
Jinja2 index.html模板如下所示:

{% for p in posts %}
    {{p}}
    {{p's AUTHOR TO BE DISPLAYED HERE. Example: author.name, author.fav_colour}}    
{% endfor %}
因此,我想知道如何显示与每个BlogPost实体关联的Author实体


谢谢。

最好的方法是对数据进行非规范化,并在BlogPost中存储作者姓名的副本:

BlogPost(ndb.Model):
    title = ndb.StringProperty()
    body = ndb.TextProperty()
    author_key = ndb.KeyProperty()
    author_name = ndb.StringProperty(indexed=False)
这样你就有了作者的名字。否则,您需要获取blogpost列表,然后对于每个blogpost,获取Author实体以获取名称。这会慢得多,也会贵得多

{{p's AUTHOR TO BE DISPLAYED HERE. Example: p.author.get.name, p.author.get.fav_colour}}    
请注意,每次为作者执行get时,这将执行2 ndb rpc调用,并将影响性能。

您可以使用memcache将作者实体存储在memcache中,或者将作者信息反规范化并存储在post实体中。

以下是查询每个作者的方法:

BlogPost(ndb.Model):
    title = ndb.StringProperty()
    body = ndb.TextProperty()
    author_key = ndb.KeyProperty()

    def get_author_async(self):
        self._author_fetch = author_key.get_async()

    @property
    def author_name(self):
        author = self_author_fetch.get_result()
        return author.name if author else ""


class BlogPostHandler(webapp2.RequestHandler): 
    def get(self):
        posts = BlogPost.query().fetch()
        for post in posts:
            post.get_author_async()
        self.render('index.html', posts = posts) #renders in Jinja2 template

是的,这在前面是比较容易的,但是假设你的博客应用程序和大多数博客一样,每个帖子都会被编辑几次,浏览1000次,那么这是一种昂贵的方式。

谢谢你的回答,@dragonx。这个解决方案似乎有很多挑战。如果在Author实体中有更多的属性呢?当然,我不能在博客类文章中包含这些内容的副本。此外,在编辑一个作者实体时,我似乎还需要检索与该作者相关的所有BlogPost实体,并在那里编辑其字段。我没有意识到这一点;事实上,我有一些实体,它们可以进行更多的ndb调用。我对数据非规范化非常陌生,这是我刚刚开始阅读的一个主题。你可以发送一些链接,让我在GAE上了解更多关于非规范化的工作原理,或者如何开始吗?谷歌开发者团队有很好的视频资源。你可以在下面的链接中找到视频集,如果它解决了你的问题,你可以接受答案。