Django antipatterns 〉antipattern 〉Giving related_name=… the same name as the relation Fork me on GitHub

Often one sees modeling with:

from django.db import models

class Profile(models.Model):
    pass

class Post(models.Model):
    author = models.ForeignKey(
        Profile,
        on_delete=models.CASCADE,
        related_name='author'
    )

Why is it a problem?

There is often some confusion about the related_name=… parameter [Django-doc]. This parameters specifies the name of the relation in reverse. It is thus the name of the relation to access the related Post objects for a given Profile object. Indeed, with the modeling above, we access the Post objects with:

# QuerySet of related Post objects
my_profile.author.all()

But here the relation does not hint that it deals with Posts, one here would think we obtain a single Author, or perhaps a set of Authors, not Posts.

What can be done to resolve the problem?

Give the related_name=… a proper value. Sometimes adding the …_of suffix is sufficient, like .author_of, but still that is not self-explaining, since a Profile can be an author of Posts, Images, etc.

Usually it is better to use the plural of the model name, so posts, or do not specify the related_name=…, and thus use modelname_set. It becomes more tricking if there are two or more relations to the same model, because then the default related_name=… can not be used because it would collide.

Nevertheless, one should look how the source model relates to the target model, here these are the authored Posts, so we can rewrite this to:

from django.db import models

class Profile(models.Model):
    pass

class Post(models.Model):
    author = models.ForeignKey(
        Profile,
        on_delete=models.CASCADE,
        related_name='authored_posts'
    )

Then we thus query with:

# QuerySet of related Post objects
my_profile.authored_posts.all()