Django:获取对象列表的相关记录列表 [英] Django: getting the list of related records for a list of objects

查看:89
本文介绍了Django:获取对象列表的相关记录列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个与一对多相关的模型:

I have two models related one-to many:

class Person(models.Model):
    name      = models.CharField(max_length=255);
    surname   = models.CharField(max_length=255);     
    age       = models.IntegerField(); 


class Dog(models.Model):
    name      = models.CharField(max_length=255);
    owner     = models.ForeignKey('Person');

我想输出一个人的清单,并在每个人的下方输出他所拥有的狗的清单。这是我的操作方法:

I want to output a list of persons and, below each person a list of dogs he has. Here's how I can do it:

视图:

persons = Person.objects.all()[0:100];

在模板中:

{% for p in persons %}
    {{ p.name }} has dogs:<br />
    {% for d in persons.dog_set.all %}
        - {{ d.name }}<br />
    {% endfor %}
{% endfor %}

但是如果我这样做,Django将执行101个SQL查询,这是非常低效的。

But if I do it like that, Django will execute 101 SQL queries which is very inefficient.

我试图创建一个自定义管理器,该管理器可以让所有人,然后是所有狗并在python中链接它们,但后来我不能使用paginator(我的另一个问题: Django:Paginator +原始SQL查询),看起来非常难看。

I tried to make a custom manager, which will get all the persons, then all the dogs and links them in python, but then I can't use paginator (my another question: Django: Paginator + raw SQL query ) and it looks quite ugly.

是否有更优美的方式?

更新

基于@Daniel Roseman博客条目的解决方案

Solution based on blog entry by @Daniel Roseman

all_objects = Person.objects.select_related().all();

paginator = Paginator(all_objects, 100);

try:
    page = int(request.GET.get('page', '1'))
except ValueError:
    page = 1

try:
    current_page = paginator.page(page)
except (EmptyPage, InvalidPage):
    current_page = paginator.page(paginator.num_pages)

person_list = dict([(obj.id, obj) for obj in current_page.object_list])
id_list = [obj.id for obj in current_page.object_list]

objects = Dog.objects.filter(owner__id__in=id_list)

relation_dict = {}
for obj in objects:
    relation_dict.setdefault(obj.owner_id, []).append(obj)

for id, related_items in relation_dict.items():
    person_list[id].dogs = related_items


推荐答案

使用Django的较新版本(> = 1.7或什至是一些较旧的版本),您只需替换您的

With the newer versions of Django (>=1.7 or maybe even some older ones) you can just replace your

persons = Person.objects.all()[0:100]

persons = Person.objects.prefetch_related('dog_set').all()[0:100]

它,如果您使用的是Django> = 1.7

and that's it, no need to keep using the old workaround if you are on Django>=1.7

prefetch_related 在这里:
https:// docs .djangoproject.com / en / 2.0 / ref / models / querysets /#prefetch-related

这篇关于Django:获取对象列表的相关记录列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆