656

What is the related_name argument useful for on ManyToManyField and ForeignKey fields? For example, given the following code, what is the effect of related_name='maps'?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))
zjm1126
  • 63,397
  • 81
  • 173
  • 221
  • 18
    @DanielRoseman Is it somehow good for performance or good practice to use related_name='+' when backwards relation is not necessary? – lajarre Oct 25 '12 at 23:02
  • 14
    I'd be curious to know the answer to @lajarre's question. – 3cheesewheel Sep 13 '13 at 15:28
  • 2
    @lajarre - I assume that won't change performance at all. I've had to use it once with FeinCMS content types. I personally think it's good practice to always specify the `related_name` so if you know you won't use it, I guess it's a good thing. That's a personal opinion of course. – François Constant Mar 24 '17 at 07:20
  • 3
    @3cheesewheel it's in the docs now: https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey.related_name `+` means do not create reverse relation – Myer May 01 '18 at 15:00

6 Answers6

870

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.

3cheesewheel
  • 9,133
  • 9
  • 39
  • 59
Wogan
  • 70,277
  • 5
  • 35
  • 35
  • 6
    Okay, I know this is an old post. But I'm just trying to figure this out - what's the + trick at the end of the related name? For instance, what happens if I did `related_name='maps+'` in the example above? – Sidd May 07 '14 at 04:12
  • 41
    if you add the +, django disables the mapping – josephmisiti Jun 16 '14 at 15:04
  • 11
    for OneToOneField default related_name will be small case class name. For example in the given example if members would be OneToOnefield then "User.map" will work. – ancho Nov 12 '14 at 09:44
  • if you specify `related_name`, does `_set` still work in `django1.11 >` ?? – E_K Sep 03 '18 at 14:54
  • 31
    I use Django 2.1.3 and I can note those are exclusive. Once `related_name` is specified, `_set` does not work anymore. – stockersky Dec 03 '18 at 21:07
153

To add to existing answer - related name is a must in case there 2 FKs in the model that point to the same table. For example in case of Bill of material

@with_author 
class BOM(models.Model): 
    name = models.CharField(max_length=200,null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    tomaterial =  models.ForeignKey(Material, related_name = 'tomaterial')
    frommaterial =  models.ForeignKey(Material, related_name = 'frommaterial')
    creation_time = models.DateTimeField(auto_now_add=True, blank=True)
    quantity = models.DecimalField(max_digits=19, decimal_places=10)

So when you will have to access this data you only can use related name

 bom = material.tomaterial.all().order_by('-creation_time')

It is not working otherwise (at least I was not able to skip the usage of related name in case of 2 FK's to the same table.)

Ilya Bibik
  • 3,924
  • 4
  • 23
  • 48
  • 4
    You have to pick a related_name at least for one of them. The other one doesn't enecssarily require. – Csaba Toth Nov 22 '16 at 22:05
  • 62
    `related_name` should be plural. Because ForeignKey relations return multiple objects. – Mesut Tasci Nov 30 '16 at 06:40
  • 1
    sorry for the necro posting =) Mesut's comment has merit. an example of what they are mentioning would be class Employee(models.Model): manager = models.ForeignKey('self', related_name = 'manages', on_delete=models.CASCADE, blank=False, null=False) google: "Django Tips #22 Designing Better Models" for more – boar Jul 13 '20 at 20:59
  • I just saw this answer, and I'm relatively new to programming. Just wanted to ask that why would someone want to have multiple FKs pointing to the same table? Why not just use the same FK everywhere? – Aditya Singh Sep 23 '21 at 07:13
  • This also covers the case where you have defined a ManyToMany on Model A pointing to Model B, whilst at the same time Model B has a ForeignKey pointing to Model A. – PyUnchained Feb 01 '22 at 10:34
  • This answer is incorrect `related_name` should refer to the parent class, not the ForeignKey reference – thecircleisround Jul 23 '22 at 13:28
  • @PyUnchained isn't that bad modeling? – M.Ionut Oct 31 '22 at 10:37
  • 1
    @AdityaSingh imagine a 'product' table with two FKs to a 'location' table - one 'manufacture_location' and one 'warehouse_delivery_location' – java-addict301 Jun 05 '23 at 19:19
  • @java-addict301 Thanks for the explanation – Aditya Singh Jun 09 '23 at 23:38
32

The related_name argument is also useful if you have more complex related class names. For example, if you have a foreign key relationship:

class UserMapDataFrame(models.Model):
    user = models.ForeignKey(User) 

In order to access UserMapDataFrame objects from the related User, the default call would be User.usermapdataframe_set.all(), which it is quite difficult to read.

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.ForeignKey(User, related_name='map_data'), the call would then be User.map_data.all().

Daniel Holmes
  • 1,952
  • 2
  • 17
  • 28
15

The essentials of your question are as follows.

Since you have Map and User models and you have defined ManyToManyField in Map model, if you want to get access to members of the Map then you have the option of map_instance.members.all() since you have defined members field. However, say you want to access all maps a user is a part of then what option do you have.

By default, Django provided you with user_instance.modelname_set.all() and this will translate to the user.map_set.all() in this case.

maps is much better than map_set.

related_name provides you an ability to let Django know how you are going to access Map from User model or in general how you can access reverse models which is the whole point in creating ManyToMany fields and using ORM in that sense.

holdenweb
  • 33,305
  • 7
  • 57
  • 77
Mr. Suryaa Jha
  • 1,516
  • 16
  • 10
  • 2
    Visit https://www.revsys.com/tidbits/tips-using-djangos-manytomanyfield/ for more information about ManyToMany field in Django – Mr. Suryaa Jha Jul 29 '20 at 17:37
5

The related name parameter is actually an option. If we do not set it, Django automatically creates the other side of the relation for us. In the case of the Map model, Django would have created a map_set attribute, allowing access via m.map_set in your example(m being your class instance). The formula Django uses is the name of the model followed by the string _set. The related name parameter thus simply overrides Django’s default rather than providing new behavior.

LuFFy
  • 8,799
  • 10
  • 41
  • 59
AbrarWali
  • 607
  • 6
  • 19
1

prefetch_related use for prefetch data for Many to many and many to one relationship data. select_related is to select data from a single value relationship. Both of these are used to fetch data from their relationships from a model. For example, you build a model and a model that has a relationship with other models. When a request comes you will also query for their relationship data and Django has very good mechanisms To access data from their relationship like book.author.name but when you iterate a list of models for fetching their relationship data Django create each request for every single relationship data. To overcome this we do have prefetchd_related and selected_related

Jamil Noyda
  • 3,321
  • 2
  • 21
  • 26