What Is Related_Name Used For

What is related_name used for?

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.map_set.all().

If you do specify, e.g. related_name=maps on the User model, User.map_set will still work, but the User.maps. syntax is obviously a bit cleaner and less clunky; so for example, if you had a user object current_user, you could use current_user.maps.all() to get all instances of your Map model that have a relation to current_user.

The Django documentation has more details.

What does related_name do?

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.

what is related_name and related_query_name in django?

Related Name

Django maintains backward relation on each object for easy access to related objects. Suppose you have two models named "School" and "Student" and one school can have multiple students. So you will have model definition something like this

class School(models.Model):
name = models.CharField(max_length=55)
city = models.Charfield(max_length=55)

class Student(models.Model):
name = models.CharField(max_length=55)
school = models.ForeignKey(School)

Now if you have an school objects then you can access all students of that school with writing query explictly.

school = School.objects.get(id=1)
# Now if need all students of this school, first thing that come in your mind would be
Student.objects.filter(school=school)
# But instead of this, you can access all students by
school.student_set.all()

Here student_set is the default, related name made by Django. But you can have your custom related names like this

class Student(models.Model):
name = models.CharField(max_length=55)
school = models.ForeignKey(School, related_name='students')
# Now you can do
school.students.all()

Special Character in related name

If you define related_name='+' then backward relation would not be available on object and school.student_set.all() will give you error.

If you’d prefer Django not to create a backwards relation, set related_name to '+' or end it with '+'. For example, this will ensure that the User model won’t have a backwards relation to this model:

Related Query Name

related_query_name is similar to related_name but it gets used in queryset.

If you need to apply some filter on student via school model, then you would do

School.objects.filter(student__name='abc')

But if you define related_query_name then you can do

class Student(models.Model):
name = models.CharField(max_length=55)
school = models.ForeignKey(School, related_query_name='abc')
# Now you can do
School.objects.filter(abc__name='abc')

Refer doc for further reference: https://docs.djangoproject.com/en/3.0/ref/models/fields/

Django related_name with _set function

related_name defines the name of reverse relation, so in your case, there is no model with relation contact_owner_set.

For example, if you want to access client contacts, you should use the client.contact_client attribute; if you want to get the contact's actions, you have to use the contact.action_contact attribute.

But there is no relation contact_owner_set in particular here:

self.fields['contact_owner'].queryset = self.instance.client_owner.contact_owner_set.order_by('name') 

self.instance.client_owner is Client instance and Client instance has no attribute contact_owner_set.

And you definitely have to rename your related_name by using plural for more code readability.

Difference between 'related_name' and 'related_query_name' attributes in Django?

related_name will be the attribute of the related object that allows you to go 'backwards' to the model with the foreign key on it. For example, if ModelA has a field like: model_b = ForeignKeyField(ModelB, related_name='model_as'), this would enable you to access the ModelA instances that are related to your ModelB instance by going model_b_instance.model_as.all(). Note that this is generally written with a plural for a Foreign Key, because a foreign key is a one to many relationship, and the many side of that equation is the model with the Foreign Key field declared on it.

The further explanation linked to in the docs is helpful. https://docs.djangoproject.com/en/dev/topics/db/queries/#backwards-related-objects

related_query_name is for use in Django querysets. It allows you to filter on the reverse relationship of a foreign key related field. To continue our example - having a field on Model A like:
model_b = ForeignKeyField(ModelB, related_query_name='model_a') would enable you to use model_a as a lookup parameter in a queryset, like: ModelB.objects.filter(model_a=whatever). It is more common to use a singular form for the related_query_name. As the docs say, it isn't necessary to specify both (or either of) related_name and related_query_name. Django has sensible defaults.

Using related_name in Django

Assuming you want to display all components in a loop and then display all related jobs for each component in a nested loop, your template should look something like this simplified example

{% for component in components %}
{{ component }}
{% for job in component.jobs.all %}
{{ job }}
{% endfor %}
{% endfor %}

You should then use prefetch_related to fetch all related jobs for all components in a single query. There is no need to query the jobs in your view

components = Component.objects.all().prefetch_related('jobs')

Django related_name default syntax

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.

django, what is related_name for? and how do i create shared columns to use across project?

Try this:

class AbstractClass(models.Model):
created_at=models.DateField("Created at")
created_by=models.ForeignKey(User, db_column="created_by", related_name="poll_user_created_by")
updated_at=models.DateTimeField("Updated at")
updated_by=models.ForeignKey(User, db_column="updated_by", null=True, related_name="poll_user_updated_by")
class Meta:
abstract = True

And then use it as base for other models:

class Poll(AbstractClass):
question=models.CharField(max_length=300)
start_poll_at=models.DateTimeField(null=True)
end_poll_at=models.DateTimeField(null=True)
is_active=models.BooleanField(default=True)

This is the django documentation about this: http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes



Related Topics



Leave a reply



Submit