Django - 反向查找

时间:2011-07-08 17:48:21

标签: django django-models reverse-lookup

例如,我有这个模型:

class Person(models.Model):
    name = models.CharField(max_length=20)
    employer = models.CharField(max_length=20)

class Car(models.Model):
    person = models.ForeignKey(Person)
    name = models.CharField(max_length=10)
    model = models.CharField(max_length=10)
    ...

好吧,我想让所有人了解自己的具体车型:

people = Person.objects.filter(car__name="Toyota")

现在我想写下这些人的汽车细节。我可以这样做:

for person in people:
   ...
   cars = person.car_set.filter(name="Toyota")
   ...

但它是下一个数据库。我怎么能避免这个?有没有办法做到这一点更简单?

3 个答案:

答案 0 :(得分:3)

首先在车名

时选择汽车和相关人员
cars = Car.objects.select_related("person").filter(name="Toyota").order_by("person")

现在你拥有所有名称为丰田的汽车以及该汽车的人,按人数排序。

现在使用python itertools.groupby为每个人分组此列表

from itertools import groupby
for k, g in groupby(cars, lambda x: x.person):
       person = k
       cars = list(g)

现在在那次迭代中你有了这个人和他的车(名字叫“丰田”)。 您会注意到只发生了一个查询,然后对缓存的信息执行以下操作。

答案 1 :(得分:0)

结帐select_related(),我之前使用它将许多跨多个模型的小查询转换为一个大型查询:https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related

它的工作原理是预先填充QuerySet,因此您对car_set的访问权限已经存在,不会产生新的查询。

答案 2 :(得分:0)

我不相信无论如何都要避免额外的数据库命中。如果您担心提出太多查询,可以尝试这样的事情:

from collections import defaultdict

cars = Car.objects.filter(**kwargs).selected_related('person')
owners = defaultdict(list)

for car in cars:
    owners[car.person].append(car)

这应该只是一个选择所有相关汽车和相关人员数据的查询