在django-MPTT中重新排序子节点

8
我正在使用Ben Firshman的django-MPTT 分支(感谢Daniel Roseman推荐)。
我试图重新排序共享相同父级的节点。我有一个主键列表,像这样:
ids = [5, 9, 7, 3]

所有这些节点都有一个父节点,假设其主键为1。
目前,这些节点的顺序是[5, 3, 9, 7],如何将它们重新排序为[5, 9, 7, 3]?
我尝试了类似于以下内容:
last_m = MyModel.get(pk = ids.pop(0))
last_m.move_to(last_m.parent, position='first-child')

for id in ids:
  m = MyModel.get(pk = id)
  m.move_to(last_m, position='right')

我希望它能按照 move_to文档所述做我想要的事情,但它似乎没有改变任何东西。有时它似乎会将ids中的第一个项目移动到其父项的第一个子项,有时则不会。
如果我在阅读move_to文档时理解正确,那么在兄弟节点上使用n调用move_to,并将position=right和目标设为n将使n立即移动到目标后面,这样对吗?
我可能已经在尝试弄清楚这个问题时搞砸了我的模型表,所以也许上面的代码实际上是正确的。也可能有一种更优雅的方法来实现这一点(也许不涉及O(n)选择和O(n)更新)。
我是否误解了什么?
奖励问题:有没有一种方法可以强制django-MPTT重建给定模型的所有实例的lftrght值?
1个回答

7
我认为这是MPTT中一个故障的结果,我之前提到过-当您移动节点时,它会正确更新您正在移动的节点实例,但不会更新目标实例(虽然它在数据库中得到更新)。
这意味着,在您的代码中,每个都会移到的右边-但中的值仍反映移动之前的位置,因此下一次移动使用原始的lft / right值而不是新的移动后的值。
解决方案是每次重新加载。
for id in ids:
  last_m = MyModel.objects.get(pk=last_m.id)
  m = MyModel.get(pk = id)
  m.move_to(last_m, position='right')

我怀疑这与那个有关 - 读了你对MPTT问题的几个回答后。我会尝试一下。你对附加问题有什么想法吗? - Dominic Rodger
@Daniel - 那个循环忘记关闭了。你的答案很好用。但我还是有点担心MPTT和树可能会进入错误状态,你有什么管理技巧吗? - Dominic Rodger
6
这是一个旧问题,但对于任何找到这里的人 - 你可以使用ModelName.tree.rebuild()重新构建MPTT树。如果你已经定义了MPTTMeta order_insertion_by字段并且需要更新树的顺序,则此方法非常有用。 - Nagyman
如果所需节点是根节点,move_to函数将不会改变顺序,只会将该节点转换为根节点。您有改变根节点顺序的解决方案吗? - Ebrahim Abdollahian
要移动根节点,您可以使用move_to函数,并带有左右参数。 - Ebrahim Abdollahian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接