这个Django应用程序教程中的choice_set是什么?

196
在 Django 教程中有这样一句话:编写你的第一个 Django 应用程序,第 1 部分
p.choice_set.create(choice='Not much', votes=0)

choice_set是在哪里被创建并且它是什么?

我猜choice部分是教程中使用的模型Choice的小写版本,但是choice_set是什么?你能详细说明一下吗?

更新: 基于Ben的答案,我找到了这份文档:反向关联


我本应该只是链接到那份文档,它比我的回答更清晰明了。 - Ben James
1
@Ben James:不,我很感激以另一种方式表达它,特别是ORM正在做什么的阐述。Django文档有时可能会简洁。 - Peter Mortensen
52
谢谢您的提问,我对此感到困惑,因为教程中没有解释。 - claudio
7
哇,对于新手来说,这一行代码是个大挑战。对我来说,难点在于理解我们正在获取一个与问题相关的选项对象(Choice Object),然后将其choice.votes增加一。至此,教程中还没有提到RelatedManager概念,因此这可能会成为真正的绊脚石。 - frozenjim
3
@HemantKumar,我试图修正文档,但未获批准。如果你遇到同样的问题,欢迎在PR中发表评论:https://github.com/django/django/pull/13330 - Escachator
显示剩余2条评论
2个回答

234

你在 Choice 模型中创建了一个外键,将每个选项与一个 Question 相关联。

因此,每个 Choice 显式地具有一个在模型中声明的 question 字段。

Django 的 ORM 向后跟踪关系,从 Question 自动为每个实例生成一个名为 foo_set 的字段,其中 Foo 是具有 ForeignKey 字段指向该模型的模型。

choice_set 是一个 RelatedManager,它可以创建查询集,包含与 Question 实例相关的 Choice 对象,例如 q.choice_set.all()

如果你不喜欢 Django 自动选择的 foo_set 命名方式,或者如果你有多个外键指向同一模型并需要区分它们,你可以使用 related_name 参数选择自己的覆盖名称。


谢谢。我现在了解更多了。choice_set是一个“Manager”吗?(它可以返回QuerySet类的实例)。还是说它是同一件事情? - Peter Mortensen
3
你是正确的,它是一个可以创建查询集的RelatedManager。 - Ben James

2

这里有两个重要的问题:第一:如何创建choice_set第二:它是什么?

对于像我这样的新开发人员,让我描述一下我如何简化它。首先回答第二个问题。“它是什么”,通过这三个词?模型实例、与该实例相关的对象集、关联管理器

Django教程中的models.py:

from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

实例:

q = Question.objects.get(pk=3)
# Here q is an instance of model class 'Question'.

c = Choice.objects.get(pk=32)
# Here c is an instance of model class 'Choice'.

'Model Instance' is a single 'ROW' of an entire 'TABLE' of your database

在这里,Question Model 作为 Choice Modelforeign key 被使用。因此,可以通过以下方式筛选与实例 q 相关的所有 对象集合
q.choice_set.all()

因此,这里的choice_set是与pk=3的问题相关的所有选项。
现在,第一个问题的答案需要第三个单词Related Manager。Django文档在这里中解释道:如果一个模型有一个ForeignKey,那么外键模型的实例将可以访问返回第一个模型的所有实例的Manager。默认情况下,这个Manager的名称为FOO_set,其中FOO是源模型名称的小写形式。这个Manager返回QuerySets,可以像上面的“检索对象”部分所述的那样进行过滤和操作。
可以使用Foreign_key中的“related_name”参数来更改这个词(choice_set)。
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name="choices")

对于通过外键进行的反向关系:

q.choice_set.all()
# If using related_name, then it is same as 
q.choices.all()

# All the choices related to the instance q.

前向关系:

choice_qs = Choice.objects.all()
choice_qs.filter(question=q)
# Same result as above. All the choices related to instance q.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接