Проблема с созданием набора запросов из объектов модели Django с самореферентным 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' object has no attribute '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() возвращает аналогичную ошибку атрибута.

Моя цель состоит в том, чтобы объекты Choice опционально имели список объектов Choice, если результат выбора приводит к дальнейшему выбору.

Вы определили это неправильно. ForeignKey действует как отношение many-to-one, а не как отношение one-to-many. Таким образом, ForeignKey всегда указывает на родителя, а не на его детей.

Таким образом, эта ForeignKey должна быть названа parent, а related_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
    )
    parent = models.ForeignKey(
        'self',
        related_name='subChoices',
        blank=True,
        null=True,
        on_delete = models.CASCADE
  )
  created_at = models.DateTimeField(auto_now_add=True)
  updated_at = models.DateTimeField(auto_now=True)
Вернуться на верх