django-mptt: как успешно переместить узлы

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

Как я заставляю детей перемещаться, и их корень не повреждается?

5
задан Parand 14 June 2010 в 19:21
поделиться

1 ответ

Внутренние значения 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()

У меня были похожие проблемы некоторое время назад, и этот подход решил мою проблему.

6
ответ дан 14 December 2019 в 08:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: