在Django中,“ related_name”是用来做什么的?

问题:在Django中,“ related_name”是用来做什么的?

related_name参数对on ManyToManyFieldForeignKeyfield有什么用?例如,给定以下代码,的作用是related_name='maps'什么?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))

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'))

回答 0

related_name属性指定从User模型回到模型的反向关系的名称。

如果不指定related_name,Django会自动使用带有后缀的型号的名称创建一个_set,例如User.map_set.all()

如果确实related_name=mapsUser模型上指定,User.map_set则仍然可以使用,但是User.maps.语法显然更简洁,更简洁。因此,例如,如果您有一个用户对象current_user,则可以current_user.maps.all()用来获取Map模型中与关联的所有实例current_user

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.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.


回答 1

要添加到现有答案中-如果模型中有2个FK指向同一张表,则必须使用相关名称。例如物料清单

@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)

因此,当您必须访问此数据时,您只能使用相关名称

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

否则它将无法正常工作(至少在同一张表中有2个FK的情况下,我无法跳过相关名称的使用。)

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.)


回答 2

related_name如果您具有更复杂的相关类名,则该参数也很有用。例如,如果您具有外键关系:

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

为了UserMapDataFrame从related中访问对象User,默认调用为User.usermapdataframe_set.all(),这很难阅读。

使用,related_name您可以指定一个更简单或更清晰的名称来获取反向关系。在这种情况下,如果您指定user = models.ForeignKey(User, related_name='map_data'),则呼叫将为User.map_data.all()

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


回答 3

相关的名称参数实际上是一个选项。如果我们不设置它,Django会自动为我们创建关系的另一面。对于Map模型,Django将创建一个map_set属性,从而允许m.map_set在您的示例中访问(m是您的类实例)。Django使用的公式是模型的名称,后跟字符串_set。因此,相关的name参数仅覆盖Django的默认值,而不提供新的行为。

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.


回答 4

prefetch_related用于预取多对多和多对一关系数据的数据。 select_related是从单个值关系中选择数据。这两个都用于从模型的关系中获取数据。例如,您构建一个模型以及一个与其他模型有关系的模型。当请求到来时,您还将查询他们的关系数据,并且Django具有很好的机制来从他们的关系中访问数据,例如book.author.name,当您迭代用于获取其关系数据的模型列表时,Django会为每个单个关系数据创建每个请求。为了克服这个问题,我们确实有 prefetchd_relatedselected_related

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