How to Reverse Lookups of Foreign Keys in Django

Vaibhav Vaibhav Feb 02, 2024
How to Reverse Lookups of Foreign Keys in Django

Django is an efficient web development framework that simplifies the creation of web applications. Django makes it effortless to deal with authenticating and authorizing, creating HTML templates, dealing with static files, interacting with databases, and performing CRUD operations over them.

Speaking of databases, Django simplifies most of the queries you can make while working with databases. One such query is the reverse look; an example is when we have to get all the objects of a table that are referencing a particular record of either the same table or a different model.

This article will show how simple it is to perform reverse lookups of foreign keys in Django.

Reverse Lookups in Django Models

Before we move onto the actual step, we need some models or tables for demonstration. We will consider two entities: teacher and student. The student has two types of teachers; a class teacher and a favorite teacher. The Student model is referencing the Teacher model.

from django.db import models


class Teacher(models.Model):
    name = models.CharField(max_length=200)
    subject = models.CharField(max_length=200)


class Student(models.Model):
    name = models.CharField(max_length=200)
    classTeacher = models.ForeignKey(
        Teacher, on_delete=models.SET_NULL, null=True, related_name="classTeacherOf"
    )
    favouriteTeacher = models.ForeignKey(
        Teacher, on_delete=models.SET_NULL, null=True, related_name="favouriteTeacherOf"
    )

Two fields of the Student model are referencing the Teacher model. In Django, when referencing the same model more than once, we have to provide a related_name for all the fields because Django’s default related_name for a single referencing field clashes with other referencing fields. Otherwise, Django will throw an exception.

The related_name is what we use for the reverse lookup. In general, it is a good practice to provide a related_name for all the foreign keys rather than using Django’s default-related name.

Example 1

We have a teacher whose id is 1. If we have to get all the students who have this individual as their class teacher, we will do the following:

teacher = Teacher.objects.get(id=1)
students = teacher.classTeacherOf.all()
print(students)  # A QuerySet of Student objects

Notice how we are using the related_name. The teacher.classTeacherOf is a manager object which means that we call methods like all(), filter(), exclude() on it.

Example 2

We have a teacher whose id is 6. If we have to get all the students who regard this teacher as their favorite teacher, we will do something like this:

teacher = Teacher.objects.get(id=6)
students = teacher.favouriteTeacherOf.all()
print(students)  # A QuerySet of Student objects

Example 3

We have a teacher whose id is 25. If we have to check whether this teacher is the class teacher of a student whose id is 5, we will do something as follows:

teacher = Teacher.objects.get(id=25)
student = teacher.classTeacherOf.filter(id=5)
print(student)  # A QuerySet of either 1 or 0 Student

Note that if no objects are found in the reverse lookup, an empty QuerySet is returned.

Vaibhav Vaibhav avatar Vaibhav Vaibhav avatar

Vaibhav is an artificial intelligence and cloud computing stan. He likes to build end-to-end full-stack web and mobile applications. Besides computer science and technology, he loves playing cricket and badminton, going on bike rides, and doodling.

Related Article - Django Object