Проблема с созданием набора запросов из объектов модели 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)