Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 246
Jibin Avatar asked Aug 06 '18 07:08

Jibin


People also ask

What is Related_name in Django?

The related_name attribute specifies the name of the reverse relation from the User model back to your model. If you don't specify a related_name, Django automatically creates one using the name of your model with the suffix _set, for instance User.

What is related name used for?

Using the related_name allows you to specify a simpler or more legible name to get the reverse relation. In this case, if you specify user = models.

How do I create a one to many relationship in Django?

One to many relationships in Django models. To define a one to many relationship in Django models you use the ForeignKey data type on the model that has the many records (e.g. on the Item model). Listing 7-22 illustrates a sample of a one to many Django relationship.

What is On_delete in Django?

The on_delete method is used to tell Django what to do with model instances that depend on the model instance you delete. (e.g. a ForeignKey relationship). The on_delete=models. CASCADE tells Django to cascade the deleting effect i.e. continue deleting the dependent models as well.


2 Answers

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.

like image 138
cezar Avatar answered Oct 27 '22 20:10

cezar


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.

like image 22
Willem Van Onsem Avatar answered Oct 27 '22 19:10

Willem Van Onsem