Переупорядочение дочерних узлов в django-MPTT - PullRequest
7 голосов
/ 24 февраля 2010

Я использую вилку Бена Фиршмана django-MPTT (наконечник шляпы до Даниэль Роузман для рекомендации ).

Я застрял, пытаясь изменить порядок узлов, которые имеют общего родителя. У меня есть список первичных ключей, например:

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, которые вызывают move_to на узле n с position=right, а цель, которая является родным братом n, сразу же переместится на n на цель?

Возможно, я испортил свою таблицу моделей, пытаясь понять это, поэтому, возможно, приведенный выше код на самом деле прав. Также возможно, что есть гораздо более элегантный способ сделать это (возможно, не включающий O(n) выбор и O(n) обновления).

Я что-то не так понял?

Дополнительный вопрос: есть ли способ заставить django-MPTT перестроить значения lft и rght для всех экземпляров данной модели?

1 Ответ

5 голосов
/ 24 февраля 2010

Я думаю, что это является артефактом сбоя в MPTT, о котором я упоминал ранее - когда вы перемещаете узлы, он корректно обновляет экземпляр перемещаемого узла, но не обновляет экземпляр цель (хотя она обновляется в базе данных).

Следствием этого является то, что в вашем коде каждый m перемещается вправо от last_m - но значения в last_m по-прежнему отражают позицию перед перемещением, поэтому при следующем перемещении используется оригинал значения lft / right вместо новых значений после перемещения.

Решение заключается в перезагрузке 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')
...