在Google App Engine上从Django中的数据存储区检索列表中每个项目的引用对象的好方法是什么

时间:2011-05-24 11:07:25

标签: google-app-engine django-nonrel

我在Google App Engine上使用Django-nonrel并拥有以下模型(它们已经过简化)。

class Author(models.Model):
    name = models.CharField()

class Book(models.Model):
    author = models.ForeignKey(Author)
    title = models.CharField()

所以,如果我这样查询,

books = Book.objects.all()

并将图书传递给模板,并按如下所示进行显示,

<ul>
{% for book in books %}
   <li>{{ book.title }}{{ book.author.name }}</li>
{% endfor %}
</ul>

由于book.author.name,我在AppStats看到了一堆datastore.get。我认为在查询书籍时我应该使用select_related(),但显然django nonrel不支持,因为Google App Engine上没有JOIN。

有人能教我如何处理这种情况吗?我应该考虑对模型进行非规范化吗?如果你告诉我你如何使用它,将不胜感激。

谢谢, 柳

2 个答案:

答案 0 :(得分:1)

这是因为引用属性中发生的RPC调用次数。您应该预取引用属性以克服RPC开销。我不知道如何在django-nonrel中预取引用属性。尼克看看这个blog。这解释了如何克服appengine中的引用属性RPC开销。在django-nonrel你应该自己想一想。

答案 1 :(得分:1)

我很难在Django-Nonrel中找到get_value_from_datastore的方法,因为Abdul说了几天。但没有运气。所以我终于在Twitter上问@wkornewald,然后他指出我使用model.<foreignkey>_id

现在,我将Nick的解决方案移植到了Django-nonrel。我对Python比较陌生,所以这可能不是很好的编码,但可以按照我的预期工作。

def prefetch_refprop(entities, prop_id, prop, filter):
    ref_ids = [getattr(x, prop_id) for x in entities]
    ref_entities = dict((x.id, x) for x in filter(id__in=ref_ids))
    for entity, ref_id in zip(entities, ref_ids):
        setattr(entity, prop, ref_entities[ref_id])
    return entities   

#Usage
books = Book.objects.filter(...)
prefetch_refprop(books, 'author_id', 'author', getattr(Author.objects, 'filter'))

谢谢大家 柳