What does related_name do?

  1. If in a model you have a ForeignKey field (this means you point through this field to other model):

    class Author(models.Model):
        name = ......
        email = .....
    
    class Article(models.Model):
        author = models.ForeignKey(Author)
        title= ....
        body = ....
    

    if you specify related_name on this field

    class Article(modles.Model):
        author = models.ForeignKey(Author, related_name='articles')
    

    you give a name to the attribute that you can use for the relation (named reverse realationship) from the related object back to this one (from Author to Article). After defining this you can retrieve the articles of an user like so:

    author.articles.all()
    
  2. If you don't define a related_name attribute, Django will use the lowercase name of the model followed by _set (that is, in our case, article_set) to name the relationship from the related object back to this one, so you would have to retrieve all articles of an user like so:

    author.article_set.all()
    
  3. If you don't want to be possible a reverse relationship (from the model to which points your ForeignKey filed to this model (the model in which the ForeignKey field is defined) you can set

    class Author(models.Model):
        author = models.ForeignKey(User, related_name='+')
    

When you create a foreign key, you are linking two models together. The model with the ForeignKey() field uses the field name to look up the other model. It also implicitly adds a member to the linked model referring back to this one.

class Post(models.Model):
    # ... fields ...

class Comment(models.Model):
    # ... fields ...
    post = models.ForeignKey(Post, related_name=???)

There are three possible scenarios here:

1. Don't specify related_name

If you don't specify a name, django will create one by default for you.

some_post = Post.objects.get(id=12345)
comments = some_post.comment_set.all()

The default name is the relation's name + _set.

2. Specify a custom value

Usually you want to specify something to make it more natural. For example, related_name="comments".

some_post = Post.objects.get(id=12345)
comments = some_post.comments.all()

3. Prevent the reverse reference from being created

Sometimes you don't want to add the reference to the foreign model, so use related_name="+" to not create it.

some_post = Post.objects.get(id=12345)
comments = some_post.comment_set.all() # <-- error, no way to access directly

related_query_name is basically the same idea, but when using filter() on a queryset:

posts_by_user = Post.objects.filter(comments__user__id=123)

But to be honest I've never used this since the related_name value is used by default.

Tags:

Django