Reverse relationship in Django

Allwin Raju
2 min readDec 25, 2020

This blog post teaches you about the relationship between the child and parent models and vice versa. Let us consider the following School and Student models for example.

Photo by Aditya Romansa on Unsplash

The student model will have the student name and the school model will have the school name alone for simplicity.

This is how our models look like.

from django.db import models


class School(models.Model):
name = models.CharField(max_length=100)

def __str__(self):
return self.name


class Student(models.Model):
name = models.CharField(max_length=100)
school = models.ForeignKey(School, on_delete=models.CASCADE, related_name='student')

def __str__(self):
return self.name

Direct relationship

In the above Student model, the school field has a foreign key relationship with the school model.

This is an example of a direct relationship. If we wish to get the school name from a student object we can simply do the following.

>>> from student.models import Student
>>> student = Student.objects.all().first()
>>> student
<Student: John>
>>> student.school.name
'Stanford'

Or if you want to query all the students whose school name is ‘Stanford’ we can simply do the following.

>>> students = Student.objects.filter(school__name='Stanford')
>>> students
<QuerySet [<Student: John>]>

This is straightforward and simple, right? We are accessing the parent object from the child object. What if we want to do the opposite of this? Let us say we would like to query the parent objects based on applying some conditions to the child object.

Reverse relationship

If we look at the models, it gives us a feeling that only child objects are mapped to the parent objects and not the other way round right?

This is where the “related_name” argument comes for the rescue. This will act as a field in the model while querying parent objects based on the child models.

Let us say I need to query all the schools where a student named ‘John’ is present. Then I can do the following.

>>> from student.models import Student, School
>>> School.objects.filter(student__name='John')
<QuerySet [<School: Stanford>]>

I have a student named ‘John’ in ‘Standford’ school record. Let me add one more ‘John’ to some other school and query again. Now two schools will be returned.

>>> from student.models import School
>>> School.objects.filter(student__name='John')
<QuerySet [<School: Stanford>, <School: Harvard>]>

This is my student table records.

student table record

We have successfully filtered parent values from the child values using reverse relationship with “related_name” attribute.

Conclusion

Hope this article is helpful. Follow me for more articles on Django and Python. Happy coding!

--

--