5

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

然而,Root 不承认这些孩子。

c1.get_root() == father  # c1's root is father, instead of Root

c1 in root.get_descendants()  # False

我如何让孩子们移动并且他们的根不会被破坏?

4

2 回答 2

6

第一次保存孩子时,内部lft和值将发生变化(即方法的最后一行)。不会更新您可能躺在身边的实例。我认为一种安全的方法是每次从数据库中重新获取它们,如下所示:rghtreparent_childrensave()

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()

不久前我遇到了类似的问题,这种方法解决了我的问题。

于 2010-06-15T12:41:01.390 回答
1

最近几天,这个库真的让我很困惑—— move_to 似乎并没有真正按照我的意愿去做,而且我的树一直不同步。我提出了一个我更有信心的解决方案,但牺牲了速度和非传统性。

它围绕partial_rebuild 这里的 manager 方法。

def delete_node(self):
    if not self.parent:
        print("Should not delete root node, confusing behavior follows")
        return
    tree_id = self.tree_id
    parent = self.parent

    for child in self.get_children():
        child.parent = parent
        child.save()

    self.delete()
    Node.objects.partial_rebuild(tree_id)

如果您愿意,可以将 child.parent = parent 替换为 child.move_node(parent)

于 2017-10-06T19:30:59.580 回答