2011-07-08 15 views
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") 
    ... 

しかし、それはデータベースの次のヒットです。どうすればこれを避けることができますか?これを簡単にする方法はありますか?

答えて

3

まず選択を1つの選択クエリでなければなりません

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

は今、あなたは名前その車のための人、ordered_byの人と一緒に、トヨタですべての車を持っている車名車と関係者。

は今、あなたは(名前が「トヨタ」である)人と彼の車を持っていることの繰り返しで今、一人一人

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

のためにグループにitertools.groupbyこのリストをのpythonを使用しています。 発生したクエリは1つしかないので、キャッシュされた情報に対して次の操作が実行されます。

+0

このテクニックを使用することによる副作用の1つは、車がない人がいる場合、そのクエリでは表示されないことです。これは、クエリーがドメインオブカーズで開始されるためです。 – arustgi

0

一つの大きなクエリに複数のモデルをまたがる多くの小さなクエリをオンにする前に、私はそれを使用しました、select_related()をチェックアウト:https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related

car_setへのアクセスは、すでにになりますので、それは、QuerySetを事前に取り込むことによって動作しますそこに新しいクエリが返されることはありません。

+0

再度フィルタリングする必要がある場合でも、私はすべての車を望んでいないが、Toyotasだけ。 – yetty

+0

同じ 'QuerySet'を再利用すると動作するかもしれません。 'QuerySet'キャッシングの詳細については、https://docs.djangoproject.com/en/dev/topics/db/queries/#caching-and-querysetsをご覧ください。 – kcbanner

0

追加のデータベースヒットを避けるためにとにかくはないと思います。これが唯一の関連するすべての車とその関係者に関するデータ

関連する問題