【问题标题】:What is related_name used for?related_name 是做什么用的?
【发布时间】:2011-02-08 05:08:54
【问题描述】:

related_name 参数对ManyToManyFieldForeignKey 字段有什么用?比如给定如下代码,related_name='maps'的作用是什么?

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

【问题讨论】:

  • @DanielRoseman 在不需要反向关系时使用 related_name='+' 对性能或良好实践有好处吗?
  • 我很想知道@lajarre 问题的答案。
  • @lajarre - 我认为这根本不会改变性能。我不得不将它与 FeinCMS 内容类型一起使用一次。我个人认为始终指定related_name 是一种很好的做法,所以如果你知道你不会使用它,我想这是一件好事。这当然是个人意见。
  • @3cheesewheel 现在在文档中:docs.djangoproject.com/en/2.0/ref/models/fields/… + 表示不创建反向关系

标签: python django foreign-keys many-to-many


【解决方案1】:

您的问题的要点如下。

由于您有MapUser 模型,并且您在地图模型中定义了ManyToManyField,如果您想访问地图的成员那么您可以选择map_instance.members.all(),因为您已经定义了 members 字段。 但是,假设您要访问用户所属的所有地图,那么您有什么选择。

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

ma​​psma​​p_set 要好得多。

related_name 让您能够让 Django 知道您将如何从 User 模型访问 Map,或者通常如何访问反向模型,这是创建 ManyToMany 字段和使用 ORM 的重点从这个意义上说。

【讨论】:

【解决方案2】:

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

【讨论】:

    【解决方案3】:

    如果您有更复杂的相关类名,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()

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        要添加到现有答案 - 相关名称是必须的,以防模型中有 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 到同一个表的情况下跳过相关名称的使用。)

        【讨论】:

        • 您必须至少为其中一个选择一个related_name。另一个不需要。
        • related_name 应该是复数。因为 ForeignKey 关系返回多个对象。
        • 抱歉发布了 necro =) Mesut 的评论是有价值的。他们提到的一个例子是 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”了解更多
        • 我刚看到这个答案,我对编程还比较陌生。只是想问为什么有人想让多个 FK 指向同一张桌子?为什么不到处使用相同的 FK?
        【解决方案6】:

        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() 来获取与current_user 相关的Map 模型的所有实例。

        Django documentation 有更多详细信息。

        【讨论】:

        • 好的,我知道这是一篇旧帖子。但我只是想弄清楚这一点 - 相关名称末尾的 + 技巧是什么?例如,如果我在上面的示例中使用 related_name='maps+' 会发生什么?
        • 如果添加+,django会禁用映射
        • 对于 OneToOneField 默认相关名称将是小案例类名称。例如,在给定的示例中,如果成员是 OneToOnefield,则“User.map”将起作用。
        • 如果您指定related_name_setdjango1.11 > 中仍然有效吗??
        • 我使用 Django 2.1.3,我可以注意到这些是专有的。一旦指定了related_name_set 就不再起作用了。
        猜你喜欢
        • 2020-05-23
        • 2023-01-11
        • 2017-10-24
        • 1970-01-01
        • 2021-05-29
        • 2011-08-24
        • 2023-04-03
        • 2014-03-04
        • 2012-05-19
        相关资源
        最近更新 更多