Django 中的“related_name”和“related_query_name”属性之间的区别?

问题描述 投票:0回答:3

您能解释一下 Django 中 Field 对象的

related_name
related_query_name
属性之间的区别吗?当我使用它们时,如何使用它们?谢谢!

python django django-models
3个回答
113
投票

related_name
将是相关对象的属性,它允许您“向后”到带有外键的模型。例如,如果
ModelA
具有如下字段:
model_b = ForeignKeyField(ModelB, related_name='model_as')
,则您可以通过转至
ModelA
来访问与您的
ModelB
实例相关的
model_b_instance.model_as.all()
实例。请注意,外键通常用复数形式编写,因为外键是一对多关系,而该等式的多方是在其上声明了外键字段的模型。

文档中链接的进一步解释很有帮助。 https://docs.djangoproject.com/en/dev/topics/db/queries/#backwards-lated-objects

related_query_name
用于 Django 查询集。它允许您过滤外键相关字段的反向关系。继续我们的示例 - 在
Model A
上有一个字段,如下所示:
model_b = ForeignKeyField(ModelB, related_query_name='model_a')
将使您能够使用
model_a
作为查询集中的查找参数,例如:
ModelB.objects.filter(model_a=whatever)
。更常见的是使用单数形式来表示
related_query_name
。正如文档所说,没有必要指定两个(或其中一个)
related_name
related_query_name
。 Django 有合理的默认值。


4
投票
class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

class Album(models.Model):
    artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)

这里外键前向关系是专辑到音乐家,后向关系是音乐家到专辑。这意味着一个专辑实例只能与一个音乐家实例相关(前向关系),而一个音乐家实例可以与多个专辑实例相关(后向关系)。
正向查询会是这样的

Album_instance.artist

注意这里的前向查询由Album_instance 和艺术家(字段名称)完成。向后将是

Musician_instance.album_set.all() 

这里使用 modelname_set 进行反向查询。

现在,如果您指定 related_name,如


    artist = models.ForeignKey(Musician, on_delete=models.CASCADE, related_name='back')

然后向后查询语法将更改 modelname_set(artist.set) 将被 back 替换。 现在向后查询

Musician_instance.back.all()

如果您不希望 Django 创建向后关系,请将 related_name 设置为“+”或以“+”结尾。

和 related_query_name 用于目标模型中的反向过滤器名称


0
投票

我用实际例子来解释一下Django模型中

related_name
related_query_name
的区别。

案例 1:默认行为(无自定义名称)

class Post(models.Model):
    title = models.CharField(max_length=100)

class Comment(models.Model):
    sentence = models.CharField(max_length=255)
    post = models.ForeignKey(Post, on_delete=models.CASCADE)

默认情况下,Django 设置:

  • related_name = 'comment_set'
    (用于反向关系访问)
  • related_query_name = 'comment'
    (用于过滤)

这会导致以下行为:

# Using related_query_name (for filtering)
Post.objects.filter(comment__title="XYZ")  # ✅ Valid
Post.objects.filter(comment_set__title="XYZ")  # ❌ Error

# Using related_name (for accessing related objects)
post_obj.comment_set.all()   # ✅ Valid
post_obj.comment.all()       # ❌ Error

案例2:自定义 related_name

class Post(models.Model):
    title = models.CharField(max_length=100)

class Comment(models.Model):
    sentence = models.CharField(max_length=255)
    post = models.ForeignKey(
        Post, 
        on_delete=models.CASCADE, 
        related_name="mycomments"  # Custom related_name
    )

当您指定自定义

related_name
时,Django会自动使用:

  • related_name = 'mycomments'
  • related_query_name = 'mycomments'
    (匹配 related_name,除非明确覆盖)

这会导致:

# Using related_query_name (for filtering)
Post.objects.filter(mycomments__sentence="XYZ")   # ✅ Valid
Post.objects.filter(comment_set__sentence="XYZ")  # ❌ Error

# Using related_name (for accessing related objects)
post_obj.mycomments.all()   # ✅ Valid
post_obj.comment_set.all()  # ❌ Error

要点:

  1. related_name
    用于访问反向关系(例如,获取帖子的所有评论)
  2. related_query_name
    用于查询集中进行过滤
  3. 如果您只指定
    related_name
    ,Django 对
    related_query_name
  4. 使用相同的值
  5. 如果需要,您可以单独覆盖
    related_query_name
post = models.ForeignKey(
    Post,
    related_name='mycomments',
    related_query_name='post_comment',
    on_delete=models.CASCADE
)

这将允许:

Post.objects.filter(post_comment__sentence="XYZ")  # Uses related_query_name
post_obj.mycomments.all()  # Uses related_name
© www.soinside.com 2019 - 2024. All rights reserved.