Можно ли добавить родителя к дочернему элементу для связи с внешним ключом?

#django #django-models #django-polymorphic

#django #django-модели #django-полиморфный

Вопрос:

Допустим, у меня есть поле внешнего ключа с именем «parent» с именем related_name «children»:

 class Item(PolymorphicModel):
    title = models.CharField()
    parent = models.ForeignKey(
        "self", related_name='children', null=True, blank=True, on_delete=models.CASCADE)

class Parent(Item):
    pass

class Child(Item):
    pass
 

Почему я могу добавить дочерний элемент только к родительскому элементу, но я получаю сообщение об ошибке, если пытаюсь добавить родительский элемент к дочернему элементу?

Итак, это работает:

 p1 = Parent.objects.create(title="Parent 1")
c1 = Child.objects.create(title="Child 1")

print(p1.children)
#<PolymorphicQuerySet []>

p1.children.add(c1)
 

Но это не:

 p1 = Parent.objects.create(title="Parent 1")
c1 = Child.objects.create(title="Child 1")
print(c1.parent)
# None

c1.parent.add(p1)
# AttributeError: 'NoneType' object has no attribute 'add'
 

Должен ли я просто каждый раз добавлять в дочернее поле родительского элемента? Нет ли способа добавить к родительскому элементу дочернего элемента вместо этого? Есть ли какая-либо причина, по которой добавление к родительскому элементу дочернего элемента не работает или не должно использоваться?

Я также немного смущен тем, когда / как использовать «_set» в этом случае (если это уместно). Итак, следуя формату примера Django «Многие к одному«, следующее для меня тоже не работает:

 p1 = Parent.objects.create(title="Parent 1")
c1 = Child.objects.create(title="Child 1")
p1.children.add(c1)

print(p1.children_set.all())
# AttributeError: 'p1' object has no attribute 'children_set'

print(c1.parent_set.all())
# AttributeError: 'c1' object has no attribute 'parent_set'

print(p1.item_set.all())
# AttributeError: 'p1' object has no attribute 'item_set'
 

Ответ №1:

Поэтому я думаю, что вы путаете себя здесь с parent и child называете здесь. related_name Поле в ForeignKey основном указывает модели установить связь , чтобы быстро найти все связанные экземпляры модели с заданным ForeignKey . Когда вы вызываете p1.children , вы получаете правильный вывод, потому что нет связанных экземпляров p1 . Вы точно так же получаете правильный вывод, когда вызываете c1.parent и получаете None . Строка, которую я скопировал и вставил ниже, является причиной этого. Устанавливая null=True , вы говорите о создании экземпляра Item экземпляра (будь то Parent or Child ) с нулевым parent полем (в python значение null равно None ).

Ваша предполагаемая проблема возникает при вызове c1.parent.add() . Поскольку вы ничего не установили parent , его значение равно None , и у него также нет add() метода. Что вы должны делать, так это устанавливать parent=[some instance of Parent] . Затем, когда вы хотите получить children Parent , скажем, данный экземпляр p1 , вы можете вызвать p1.children , и вы получите набор запросов, полный Child экземпляров, parent в поле которых был установлен внешний ключ этого Parent экземпляра.

 parent = models.ForeignKey(
    "self", related_name='children', null=True, blank=True, on_delete=models.CASCADE)