Создание копии дерева страниц FeinCMS с помощью django-mptt изменяет порядок дочерних элементов

Я пытаюсь сделать копию дерева страниц FeinCMS, которое управляется с помощью django-mptt. Я написал эту функцию:

def make_tree_copy(page, parent=None):
    '''
    Makes a copy of the tree starting at "page", reparenting it to "parent"
    '''
    new_page = Page.objects.create_copy(page)
    new_page.save()
    Page.tree.move_node(new_page, parent)

    # re-read so django-mptt fields get updated
    new_page = Page.objects.get(id=new_page.id)
    for child in page.get_children():
        # re-read so django-mptt fields get updated
        child = Page.objects.get(id=child.id)
        make_tree_copy(child, new_page)

и вызовите его, используя

make_tree_copy(Page.tree.root_nodes()[0])

В целом это работает, но когда у меня есть дерево страниц, выглядящее так:

A
|- B
   |- C
   |- D

Выходит так:

A
|- B
   |- D
   |- C

Судя по коду mptt, кажется, что волшебство происходит в mptt/managers.py/_inter_tree_move_and_close_gap(), где по какой-то причине значения «lft» внуков изменяются. До хода они C=3, D=5, после - C=5, D=3.

Это объясняет, почему D сортируется перед C, но я понятия не имею, почему эти значения переключаются. Какие-нибудь мысли?


person Jonas    schedule 07.10.2010    source источник


Ответы (1)


Хорошо, я знал, как только я спрошу - я найду ответ сам (потратив несколько часов до...). Конечно, это та же проблема, что и во всех других проблемах django-mptt на StackOverflow: вам нужно перечитать объект из базы данных.

Я сделал это во фрагменте выше, но не в тех местах. Это код, который работает (перечитывая родителя при входе в рекурсивную функцию):

def make_tree_copy(page, parent=None):
    '''
    Makes a copy of the tree starting at "page", reparenting it to "parent"
    '''
    if parent:
        # re-read so django-mptt fields get updated
        parent = Page.objects.get(id=parent.id)

    new_page = Page.objects.create_copy(page)
    new_page.save()
    Page.tree.move_node(new_page, parent)

    for child in page.get_children():
        make_tree_copy(child, new_page)
person Jonas    schedule 07.10.2010
comment
Последние версии django-mptt немного умнее, когда дело доходит до обновления свойств MPTT экземпляров модели (lft, rght, level и т. д.); возможно, они работают без перезагрузки моделей снова и снова, хотя я еще не слишком много проверял. - person Matthias Kestenholz; 26.02.2011