使用自引用外键创建 Django 模型对象的查询集时遇到问题

Trouble Creating QuerySet of Django model objects with self-referential ForeignKey

简单的说我有两个模型

一个对话模型:

class Dialogue(models.Model):
  content = models.TextField()
  created_at = models.DateTimeField(auto_now_add = True)
  updated_at = models.DateTimeField(auto_now = True)

以及选择型号:

class Choice(models.Model):
  option = models.CharField(max_length = 255)
  content = models.TextField()
  dialogue = models.ForeignKey(
    Dialogue, 
    related_name = "choices", 
    blank = True, 
    null = True, 
    on_delete = models.CASCADE
  )
  subChoices = models.ForeignKey(
    "self",
    related_name = "parent",
    blank = True,
    null = True,
    on_delete = models.CASCADE
  )
  created_at = models.DateTimeField(auto_now_add = True)
  updated_at = models.DateTimeField(auto_now = True)

您可能已经注意到递归 ForeignKey“Choice.subChoices”。这就是我的问题所在。

如果我尝试通过这个模型的实例使用 add() 方法,我想将它添加到 Choice 的进一步选择列表中,我得到一个“'Choice' 对象没有属性 'add'”。如果我尝试相反并将 Choice 模型的实例添加到 Choice 的父属性,它会覆盖而不是创建查询集。

以下两者的示例:

choice1 = Choice.objects.get(id = 1)
choice2 = Choice.objects.get(id = 2)
choice3 = Choice.objects.get(id = 3)
choice1.subChoices.add(choice2)
>>> AttributeError: 'Choice' object has no attribute 'add'
choice2.parent.add(choice1)
choice3.parent.add(choice2)
print(choice1.subChoices)
>>> Choice object(3)

choice1.subChoices.all()的打印语句returns类似的属性错误。

我的目标是让 Choice 对象可选地拥有一个 Choice 对象列表,如果选择的结果导致进一步的选择。

你的定义有误。 ForeignKey 充当 多对一 关系,而不是 一对多 关系。因此 ForeignKey 总是指向父对象,而不是它的子对象。

因此 ForeignKey 应命名为 parentrelated_name 应命名为 subChoices。因此,建模应如下所示:

class Choice(models.Model):
    option = models.CharField(max_length = 255)
    content = models.TextField()
    dialogue = models.ForeignKey(
        Dialogue,
        related_name='choices',
        blank=True, 
        null=True, 
        on_delete=models.CASCADE
    )
    <strong>parent</strong> = models.ForeignKey(
        'self',
        <strong>related_name='subChoices'</strong>,
        blank=True,
        null=True,
        on_delete = models.CASCADE
  )
  created_at = models.DateTimeField(auto_now_add=True)
  updated_at = models.DateTimeField(auto_now=True)