Search code examples
djangodjango-modelsreverse-lookup

Django - reverse lookups


For example, I have these models:

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

I want to get all people who own some specific car:

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

Now I want to write these people out with details about their own car. I can do this:

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

But it hit the database again. How can I avoid this? Is there any way to do this simpler?


Solution

  • First select the car and the related person when the car name

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

    Now you have all the cars whose name is toyota along with the person for that car, ordered_by person.

    Now use the python itertools.groupby to group this list for each person

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

    Now in that iteration you have the person and his cars (whose name is "toyota"). You'll notice that there is only single query that occurs, and then the following operations execute on the cached information.