Jibin
Jibin

Reputation: 3102

Django related_name default syntax

According to the documentation, related names must be unique. Again according to the documentation the default value, (if not set explicitly by the developer) is FOO_set, where FOO is the source model name.

So if I have two foreign keys (pointing to two different models, of course), wouldn't the (default) related names be similar?

Upvotes: 5

Views: 4622

Answers (2)

cezar
cezar

Reputation: 12032

I'd like to extend the excellent answer of Willem Van Onsem. In his example the class C is related to the classes A and B. Therefore A and B have attributes c_set, but they are different classes. Thus the attributes c_set, which have the same name, exist in a different scope (namespace).

But what if the relation is of different nature. Let's take a look at different example. Imagine an application for sport teams. We have classes Person and Team. A person can play for a team or coach a team. The models would look like:

class Person(models.Model):
    name = models.CharField(max_length=255, unique=True)


class Team(models.Model):
    name = models.CharField(max_length=255, unique=True)
    place = models.CharField(max_length=255)
    players = models.ManyToManyField('Person')
    coaches = models.ManyToManyField('Person')

Now this should create an attribute team_set to the class Person:

person = Person.objects.get(pk=1)
# now we want to get the teams where the person participates
person.team_set.all()

And there is the problem! Which relation should be used - players or coaches? Django won't allow this and ask for explicit declaration of related names.

We can fix the problem by declaring the related names, for example:

players = models.ManyToManyField('Person', related_name='plays_in_teams')
coaches = models.ManyToManyField('Person', related_name='trains_teams')

After this change we can query the teams like:

person.plays_in_teams.all()
person.trains_teams.all()

This shows the usefulness of related names. They help to create human readable queries and increase the maintainability of the code.

Upvotes: 6

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477794

Given you have a model C, with ForeignKeys to A and B, like:

class A(models.Model):
    pass

class B(models.Model):
    pass

class C(models.Model):
    a = models.ForeignKey(A, on_delete=models.CASCADE)
    b = models.ForeignKey(B, on_delete=models.CASCADE)

Then there are indeed two c_sets, but these are on different models. So A objects have a c_set, and B objects have a c_set, but there is no confusion, since the type of object determines about which relation we are talking.

Frequently it makes sense however to specify a related_name=..., parameter with better nomenclature.

Upvotes: 6

Related Questions