也就是说,如果树看起来像:
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
如何让孩子们移动,他们的根不会被破坏?
答案 0 :(得分:6)
内部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()
我有一段时间similar problems,这种方法解决了我的问题。
答案 1 :(得分:1)
这个库在过去的几天里让我很困惑 - move_to似乎并不像我想要的那样,而且我的树一直不同步。我提出了一个我更有信心的解决方案,牺牲了速度和非传统性。
它围绕经理方法partial_rebuild
here。
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)