Django
related_name
database relationships
Django models
ORM

What is related_name used for?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Django, related_name controls the name of the reverse relationship created by the ORM. It matters because Django relationships work in two directions: one side stores the foreign key or many-to-many field, and the other side gets an automatically generated accessor that you often use in queries, templates, and business logic.

What Django Creates by Default

If you define a ForeignKey without related_name, Django gives the reverse side a default name based on the model name plus _set.

python
1from django.db import models
2
3
4class Author(models.Model):
5    name = models.CharField(max_length=100)
6
7
8class Book(models.Model):
9    title = models.CharField(max_length=200)
10    author = models.ForeignKey(Author, on_delete=models.CASCADE)

With that model, you can go from Book to Author through book.author, and from Author back to books through author.book_set.all().

That default is functional, but it is not always clear or expressive enough.

It also exposes Django's default naming convention to every caller of the model API. In larger projects, that often makes reverse access feel accidental instead of intentional.

You can rename the reverse accessor with related_name.

python
1from django.db import models
2
3
4class Author(models.Model):
5    name = models.CharField(max_length=100)
6
7
8class Book(models.Model):
9    title = models.CharField(max_length=200)
10    author = models.ForeignKey(
11        Author,
12        on_delete=models.CASCADE,
13        related_name="books",
14    )

Now the reverse side becomes much more readable:

python
author = Author.objects.get(pk=1)
for book in author.books.all():
    print(book.title)

That naming improvement becomes even more valuable in templates and serializers, where book_set can feel like an implementation detail instead of a domain concept.

Avoid Reverse Name Collisions

related_name is especially important when multiple fields point to the same model. Without distinct reverse names, Django cannot generate a unique reverse accessor.

python
1class Message(models.Model):
2    sender = models.ForeignKey(
3        Author,
4        on_delete=models.CASCADE,
5        related_name="sent_messages",
6    )
7    receiver = models.ForeignKey(
8        Author,
9        on_delete=models.CASCADE,
10        related_name="received_messages",
11    )

This lets you write:

python
user = Author.objects.get(pk=1)
print(user.sent_messages.count())
print(user.received_messages.count())

Without those separate names, the reverse accessors would conflict.

The same principle applies to ManyToManyField and OneToOneField. Whenever Django generates a reverse relationship, related_name lets you shape that API deliberately.

You Can Disable the Reverse Accessor Too

If you do not want Django to create a reverse relation at all, set related_name="+".

python
1class AuditEntry(models.Model):
2    actor = models.ForeignKey(
3        Author,
4        on_delete=models.CASCADE,
5        related_name="+",
6    )

That is useful when the reverse direction would be noisy, misleading, or never used.

One subtle point is that related_name affects the Python-level reverse accessor, while related_query_name affects the name used in lookups. In many cases, related_name is enough, but it helps to know they are not identical concepts.

Good related_name choices also make queryset code easier to read later. Expressions such as author.books.filter(...) communicate intent much better than generic defaults.

Common Pitfalls

  • Leaving the default reverse name in place when a clearer domain name would improve readability.
  • Forgetting related_name on multiple relations to the same model and causing reverse accessor clashes.
  • Using a plural name that does not match the relationship semantics.
  • Setting related_name="+" and then expecting reverse access later in code or templates.
  • Picking inconsistent reverse names across the project, which makes the ORM harder to learn and harder to use predictably.
  • Treating reverse accessor naming as unimportant, even though it shapes the readability of everyday queryset code.

Summary

  • 'related_name defines the reverse accessor Django creates for relationships.'
  • Without it, Django uses a default name such as book_set.
  • A custom reverse name improves readability and avoids naming conflicts.
  • It is especially important when several fields point to the same related model.
  • Use related_name="+" when you intentionally want no reverse relation.

Course illustration
Course illustration

All Rights Reserved.