5

django-mpttは、私を頭から追い出そうと決心しているようです。私は比較的単純なことをしようとしています。ノードを削除し、ノードの子に対して合理的なことをする必要があります。つまり、現在の親の子になるように、1つ上のレベルに移動したいと思います。

つまり、ツリーが次のようになっている場合:

 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

子供たちを動かして、彼らの根が壊れないようにするにはどうすればよいですか?

4

2 に答える 2

6

内部値lftrght値は、最初に子を保存するときに変更されます(つまり、メソッドの最後の行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()

私はしばらく前に同様の問題を抱えていました、そしてそのアプローチは私の問題を解決しました。

于 2010-06-15T12:41:01.390 に答える
1

このライブラリは、ここ数日本当に私を混乱させました-move_toは私が望んでいることを実際には行っていないようで、私のツリーは同期していません。私は、スピードと非伝統性を犠牲にして、より自信を持って解決策を思いつきました。

partial_rebuild ここではマネージャーメソッドを中心に展開しています。

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 に答える