2

例如,我有这些模型:

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

但它再次击中数据库。我怎样才能避免这种情况?有什么方法可以更简单地做到这一点吗?

4

3 回答 3

3

车名时先选择车和相关人

cars = Car.objects.select_related("person").filter(name="Toyota").order_by("person")

现在,您拥有所有名称为 toyota 的汽车以及该汽车的人,ordered_by person。

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

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

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

于 2011-07-10T04:49:01.177 回答
0

看看select_related(),我以前用过它把许多跨越多个模型的小查询变成一个大查询:https ://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related

它通过预先填充 来工作QuerySet,因此您的访问权限car_set已经存在并且不会导致新的查询。

于 2011-07-08T17:54:20.713 回答
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)

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

于 2011-07-08T18:04:29.503 回答