Reordering child nodes in django-MPTT

I am using Ben Firshman django-MPTT plug (hat tip to Daniel Roseman for recommendation ).

I am stuck trying to reorder nodes that have a common parent. I have a list of primary keys, for example:

ids = [5, 9, 7, 3] 

All these nodes have a parent element, for example, with primary key 1.

These nodes are currently ordered [5, 3, 9, 7] , how can I reorder them to [5, 9, 7, 3] ?

I 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 would expect to do what I want for the docs on move_to , but it does not seem to change anything. Sometimes it seems that the first element in ids moved by the first parent of its parent, sometimes it is not.

Am I reading the documents for move_to that calling move_to on node n using position=right , and the target, which is a child of n , will move n to right after the target?

Maybe I messed up the table of my models trying to figure it out, so maybe the code above is actually right. It is also possible there is a much more elegant way to do this (perhaps one that does not include O(n) and O(n) updates).

I didn’t understand something?

Bonus question: is there a way to get django-MPTT to restore lft and rght for all instances of this model?

+7
django django-mptt
source share
1 answer

I think this is the artifact of the failure in MPTT that I mentioned earlier - when you move the nodes around, it correctly updates the node instance that you are moving, but does not update the instance (although it is updated in the database).

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

The solution is to reload last_m every 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') 
+5
source share

All Articles