Skip to content

Following Relationships

Employees reviewing Peanut's adoption need to see Peanut's applications, and each application needs to say which animal it's for. Our foreign key links the two tables, and the ORM can follow it in either direction.

Following a Foreign Key Forward

Python REPL
>>> application = AdoptionApplication.objects.get(applicant_name="Maria")
>>> application.animal
<Animal: Peanut>

application.animal is the Animal the foreign key points at. Reading it the first time runs a query for that animal.

Following a Foreign Key Backward

Python REPL
>>> peanut = Animal.objects.get(name="Peanut")
>>> peanut.applications.count()
2
>>> peanut.applications.values_list("applicant_name", flat=True)
<QuerySet ['Maria', 'Aisha']>

applications is the foreign key's related_name. Every Animal has it, and it works like Animal.objects, limited to that animal's applications.

Our applications don't have a __str__ yet, so the shell would show each one as AdoptionApplication object with its id. values_list() returns the values of the fields we name instead of model instances. With flat=True and one field, each value comes back alone, not in a tuple.

Lookups Across a Relationship

Two underscores also follow a foreign key inside a lookup. animal__species is the species of the application's animal:

Python REPL
>>> AdoptionApplication.objects.filter(animal__species="cat").values_list("applicant_name", flat=True)
<QuerySet ['Maria', 'Aisha']>

A lookup can follow the relationship backward too, through the related_name:

Python REPL
>>> Animal.objects.filter(applications__applicant_name="Aisha")
<QuerySet [<Animal: Peanut>]>

Repeated rows

A backward lookup returns one row for each matching application, so an animal with two comes back twice. distinct() removes the repeats:

Python REPL
>>> Animal.objects.filter(applications__applicant_name__in=["Maria", "Aisha"])
<QuerySet [<Animal: Peanut>, <Animal: Peanut>]>
>>> Animal.objects.filter(applications__applicant_name__in=["Maria", "Aisha"]).distinct()
<QuerySet [<Animal: Peanut>]>