44

Can someone tell me what is reverse relationship means? I have started using Django and in lot of places in the documentation I see 'reverse relationship, being mentioned. What is it exactly mean? why is it useful? What does it got to do with related_name in reference to this post ?

Community
  • 1
  • 1
name
  • 571
  • 1
  • 7
  • 11

3 Answers3

89

Here is the documentation on related_name

Lets say you have 2 models

class Group(models.Model):
    #some attributes

class Profile(models.Model):
    group = models.ForeignKey(Group)
    #more attributes

Now, from a profile object, you can do profile.group. But if you want the profile objects given the group object, How would you do that? Thats' where related name or the reverse relationship comes in.

Django, by defaults gives you a default related_name which is the ModelName (in lowercase) followed by _set - In this case, It would be profile_set, so group.profile_set.

However, you can override it by specifying a related_name in the ForeignKey field.

class Profile(models.Model):
    group = models.ForeignKey(Group, related_name='profiles')
    #more attributes

Now, you can access the foreign key as follows:

group.profiles.all()
karthikr
  • 97,368
  • 26
  • 197
  • 188
  • 2
    So we can access,edit, query etc all the profile object attributes from group object or if you know the group_id? – name Jun 26 '13 at 19:52
5

For a clearer picture you can assume that when we use reverse relationship, it adds an extra field in the referenced model:

For example:

class Employee(models.Model):
           name = models.CharField()
           email = models.EmailField()
class Salary(models.Model):
           amount = models.IntegerField()
           employee = models.ForeignKey(Employee, on_delete=models.CASCADE, related_name='salary')

After using related_name in Salary model, now you can assume the Employee model will have one more field: salary.

For example, the available fields would now be:

name, email, and salary

To find an employee, we can simply query in this way:

e = Employee.objects.filter(some filter).first()

To check their salary, we can check it by writing e.salary (now we can use salary an attribute or field in employee model). This will give you the salary instance of that employee, and you can find the amount by writing e.salary.amount. This will give you the salary of that employee.

In case of many to many relationship we can use .all() and then iterate over that.

dKen
  • 3,078
  • 1
  • 28
  • 37
Nishant Yadav
  • 199
  • 2
  • 5
1

In Django 2.0 you would define a ForeignKey as follows

mainclient = models.ForeignKey( MainClient, on_delete=model.CASCADE, related_name='+')  

the related_name='+' would cancel the default reverse relationship that Django sets up, so in the previous example, you would not be able to query the profiles using group.profiles.all().

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
eb0t
  • 127
  • 1
  • 11
  • 1
    Why would you need to do this? – polarise Sep 07 '18 at 05:37
  • 3
    If you had a Status object and a TransactionHistory object that has 2 relationships from TransactionHistory to Status, call them from_status and to_status. Sure, you could give unique names to the reverse relationships in Status so you can access Status.transactionHistoriesFromStatuses and Status.transactionHistoriesToStatuses, but if your business logic would never use the reverse relationship then it would be reasonable to simply use '+' to remove the reverse relationship. – Lehrian Jan 16 '20 at 22:01