Django-反向查找

Django-反向查找,django,django-models,reverse-lookup,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 = m

例如,我有以下模型:

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")
   ...

但它再次进入数据库。我怎样才能避免这种情况?有没有更简单的方法呢?

请查看
选择相关()
,我以前用过它将许多跨越多个模型的小查询转换为一个大查询:


它的工作原理是预先填充
查询集
,因此您对
车集
的访问将已经存在,并且不会产生新的查询。

我认为无论如何都无法避免额外的数据库命中。如果您担心查询太多,可以尝试以下方法:

from collections import defaultdict

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

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

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

在输入车辆名称时,首先选择车辆和相关人员

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

即使我需要再次筛选它?我不想要每辆车,只想要丰田。如果你重复使用相同的
QuerySet
,它可能会工作。查看:有关
QuerySet
缓存的更多详细信息。使用此技术的一个副作用是,如果您有一个没有汽车的人,您将无法在该查询中看到。这是因为查询是在Cars域上启动的。