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

发布于 2024-08-23 03:22:04 字数 1340 浏览 5 评论 0原文

我正在使用 Ben Firshman 的 django-MPTT 的 fork (提示 丹尼尔·罗斯曼 推荐)。

我在尝试重新排序共享公共父节点的节点时遇到了困难。我有一个主键列表,如下所示:

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 文档的阅读是否正确,即使用 position=right 在节点 n 上调用 move_to并且作为 n 的同级目标会将 n 移动到紧随该目标之后?

我可能在试图解决这个问题时搞砸了我的模型表,所以也许上面的代码实际上是正确的。也可能有一种更优雅的方法来执行此操作(可能不涉及 O(n) 选择和 O(n) 更新)。

我是否误解了什么?

额外问题:有没有办法强制 django-MPTT 为给定模型的所有实例重建 lftrght 值?

I'm using Ben Firshman's fork of django-MPTT (hat tip to Daniel Roseman for the recommendation).

I've got stuck trying to re-order nodes which share a common parent. I've got a list of primary keys, like this:

ids = [5, 9, 7, 3]

All of these nodes have a parent, say with primary key 1.

At present, these nodes are ordered [5, 3, 9, 7], how can I re-order them to [5, 9, 7, 3]?

I've tried something like this:

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

Which I'd expect to do what I want, per the docs on move_to, but it doesn't seem to change anything. Sometimes it seems to move the first item in ids to be the first child of its parent, sometimes it doesn't.

Am I right in my reading of the docs for move_to that calling move_to on a node n with position=right and a target which is a sibling of n will move n to immediately after the target?

It's possible I've screwed up my models table in trying to figure this out, so maybe the code above is actually right. It's also possible there's a much more elegant way of doing this (perhaps one that doesn't involve O(n) selects and O(n) updates).

Have I misunderstood something?

Bonus question: is there a way of forcing django-MPTT to rebuild lft and rght values for all instances of a given model?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浮生面具三千个 2024-08-30 03:22:05

我认为这是我之前提到过的 MPTT 失败的人为因素 - 当您移动节点时,它会正确更新您正在移动的节点的实例,但不会更新目标的实例(尽管它确实在数据库中得到更新)。

这样做的结果是,在您的代码中,每个 m 都会移动到 last_m 的右侧 - 但 last_m 中的值仍然反映移动之前的位置,因此下一次移动使用原始左/右值而不是新的移动后值。

解决方案是每次重新加载 last_m

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

I think this is an artefact of a failure in MPTT that I've mentioned before - when you move nodes around, it correctly updates the instance of the node you're moving, but it doesn't update the instance of the target (although it does get updated in the database).

The consequence of this is that in your code, each m gets moved to the right of last_m - but the values in the last_m still reflect the position before the move, so the next move uses the original lft/right values instead of the new post-move ones.

The solution is to reload last_m each time:

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')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文