什么是related_name参数有用的ManyToManyField和ForeignKey字段?例如,给定下面的代码,related_name='maps'的效果是什么?

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

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

如果你没有指定related_name, Django会自动创建一个带有_set后缀的模型名,例如User.map_set.all()。

如果你在User模型上指定了,例如related_name=maps, User. map。map_set仍然可以工作,但是User.maps. set语法显然更简洁,不那么笨拙;例如,如果你有一个用户对象current_user,你可以使用current_user.maps.all()来获取所有与current_user有关系的Map模型实例。

Django文档中有更多细节。


如果模型中有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的情况下跳过相关名称的使用)。


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


如果有更复杂的相关类名,related_name参数也很有用。例如,如果你有一个外键关系:

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

为了从相关的User访问UserMapDataFrame对象,默认调用是User.usermapdataframe_set.all(),这是相当难读的。

使用related_name允许您指定一个更简单或更容易读懂的名称来获得相反的关系。在本例中,如果指定user = models。ForeignKey(User, related_name='map_data'),则调用User.map_data.all()。


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


你问题的要点如下。

既然你有Map和User模型,并且你已经在Map模型中定义了ManyToManyField,如果你想访问Map的成员,那么你有map_instance.members.all()选项,因为你已经定义了members字段。 然而,如果你想访问所有的地图用户是一个部分,那么你有什么选择。

默认情况下,Django为你提供了user_instance.modelname_set.all(),在这种情况下,这将转换为user.map_set.all()。

Maps比map_set好得多。

related_name可以让Django知道如何从用户模型访问Map,或者如何访问反向模型,这是创建多对多字段和使用ORM的关键所在。