Django:向后的ForeignKey查询

时间:2011-06-22 21:03:16

标签: django django-views

我的模特:

class NewsItem(models.Model):
    title    = ...
    content  = ...

class Image(models.Model):
    newsItem = models.ForeignKey(NewsItem)
    url      = ....

我想用他们的图像显示50个NewsItems(每个NewsItem有2-5个图像)。 我可以只使用一两个查询吗吗?我可以查询“backwars”相关信息吗?

我找到了一些有关它的信息,但不明白如何在模板中显示_related项目(在我的情况下,“向后”_相关项目是图像)。链接为http://blog.roseman.org.uk/2010/01/11/django-patterns-part-2-efficient-reverse-lookups/

文章于2010年1月发布 - 可能有更有效的方法吗?

3 个答案:

答案 0 :(得分:2)

这是一个可能更容易理解(命名)的例子。

感谢Daniel Roseman setdefault!我每天都在堆栈上学到一些东西。我一直在使用丑陋的try/except块来解决同样的问题。

查看:

newsitems = NewsItem.objects.all()[0:50]
related_images = Image.objects.filter(newsitem__in=newsitems)
newsitem_images_map = {}

for image in related_images:
    # start appending to a list keyed by the newsitem ID for all related images
    newsitem_images_map.setdefault(image.newsitem_id, []).append(image)

for newsitem in newsitems:
    # set an attribute on the newsitem that is the list created above
    newsitem.images = newsitem_images_map.get(newsitem.id)

    # this attribute is accessible from the template.

模板:

{% for newsitem in newsitems %}
    {{ newsitem.title }}
    {% for image in newsitem.images %}
        {{ image }}
    {% endfor %}
{% endfor %}

答案 1 :(得分:2)

qs = NewsItem.objects.all()
obj_dict = dict([(obj.id, obj) for obj in qs])

objects = Image.objects.filter(newsitem__in=qs)

relation_dict = {}

for obj in objects:
    relation_dict.setdefault(obj.newsitem_id, []).append(obj)
for id, related_items in relation_dict.items():
    obj_dict[id]._related_images = related_items

...
{% for newsitem in obj_dict %}
    {% for image in newsitem._related_images %}

您将在2个查询中获取相关数据

<强>更新 在Django 1.4中可用的新方法prefetch_related

顺便说一句,prefetch_related不适用于不推荐使用的通用视图direct_to_template。

newitems = NewItem.objects.prefetch_related('images')

答案 2 :(得分:-1)

你的情景不是反向关系:

news_item.images     # forward relation

image.newsitem_set  # reverse relation

所以,你需要做的就是:

news_items = NewsItem.objects.select_related().all()[:50]

并将其传递给您的模板,图片对象应该已经缓存。