django-mptt кажется полным решимости управлять мной не в своем уме. Я пытаюсь сделать что-то относительно простое: я собираюсь удалить узел и должен сделать что-то разумное с детьми узла. А именно, я хотел бы переместить их один уровень, таким образом, они - дети родителя своего текущего родителя.
Таким образом, если дерево похоже:
Root
|
Grandpa
|
Father
| |
C1 C2
Я собираюсь удалить Родительский элемент и хотел бы, чтобы C1 и C2 были детьми Дедушки.
Вот код, который я использую:
class Node(models.Model):
first_name = models.CharField(max_length=80, blank=True)
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
def reparent_children(self, parent):
print "Reparenting"
for child in self.get_children():
print "Working on", child.first_name, "to parent", parent.email
parent = Node.objects.get(id=parent.id)
child.move_to(parent, 'last-child')
child.save()
Таким образом, я звонил бы:
father.reparent_children(grandpa)
father.parent = None
father.save()
Это работает - почти. Дети сообщают о своих родителях как Дедушка:
c1.parent == grandpa # True
Количества C1 и C2 дедушки среди его детей
c1 in grandpa.children.all() # True
Однако Корень отрицает этих детей.
c1.get_root() == father # c1's root is father, instead of Root
c1 in root.get_descendants() # False
Как я заставляю детей перемещаться, и их корень не повреждается?
Внутренние значения lft
и rght
изменятся при первом сохранении дочернего объекта (т.е. в последней строке метода reparent_children
). save()
не обновляет экземпляры, которые могут лежать рядом. Я думаю, что безопасный способ сделать это - каждый раз заново получать их из базы данных, например так:
def reparent_children(self, parent):
print "Reparenting"
for child in self.get_children():
print "Working on", child.first_name, "to parent", parent.email
parent = Node.objects.get(id=parent.id)
current_child = Node.objects.get(id = child.id)
current_child.move_to(parent, 'last-child')
current_child.save()
У меня были похожие проблемы некоторое время назад, и этот подход решил мою проблему.