About the related_name Attribute

The related_name attribute at foreign keys and many-to-many relations refers to the backwards relation to this object. It is being used as a manager method and as a queryset lookup.

1
2
3
4
5
6
7
8
class Book(models.Model):
    # ...
    authors = models.ManyToManyField(
        "accounts.User",
        verbose_name=_("Authors"),
        related_name="books",
        blank=True,
    )

Then

1
2
3
4
5
6
7
8
>>> from django.db import models
>>> from accounts.models import User
>>> for author in User.objects.annotate(
...    books_count=models.Count("books")
... ).filter(books_count__gt=0):
...     print(author.get_full_name())
...     for book in author.books.all():
...         print(book.title)

If you create an abstract model with relations to other models, make sure to use the special syntax with %(app_label)s and %(class)s to have unique related names:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class EditorsMixin(models.Model):
    editors = models.ManyToManyField(
        "accounts.User",
        verbose_name=_("Editors"),
        related_name="edited_%(app_label)s_%(class)s_set",
        blank=True,
    )

    class Meta:
        abstract = True

For the Book model, it could look like this:

1
2
class Book(EditorsMixin):
    # ...

Then:

1
2
3
4
5
6
7
8
>>> from django.db import models
>>> from accounts.models import User
>>> for editor in User.objects.annotate(
...    edited_books_count=models.Count("edited_books_book_set")
... ).filter(edited_books_count__gt=0):
...     print(editor.get_full_name())
...     for book in editor.edited_books_book_set.all():
...         print(book.title)

The %(app_label)s ensures that there is no clashing from different models with the same name from different apps, for example, blog posts and forum posts.

Tips and Tricks Programming Development Databases Django 5.x Django 4.2 Django 3.2