Django-MPTT полностью глючит или я делаю это неправильно?

Я пытаюсь использовать django-mptt без особой удачи. Это с Python2.5, windows, sqlite3, Django 1.2pre, django-mptt последней из SVN.

Код:

модель:

class Node(models.Model):
    name   = models.CharField(max_length=20, blank=True)
    parent = models.ForeignKey('self', null=True, blank=True, related_name='children')

    def __unicode__(self):
        return self.name

mptt.register(Node)

настроить:

nodes = []
for i in range(15):
    n = Node(name='node'+str(i))
    n.save()
    nodes.append(n)

nodes[0].move_to(None)
nodes[0].save()
for n in range(1,15):
    nodes[n].move_to(nodes[(n-1)/2],'last-child')
    nodes[n].save()

Это должно создать дерево с одним корнем и двумя дочерними элементами, свисающими с каждого неконечного узла.

Теперь начинается самое интересное:

>>> nodes[0].children.all()
[<Node: node1>, <Node: node2>]
>>> nodes[0].get_descendants()
[]

>>> nodes[0].get_descendants(True)
[<Node: node0>, <Node: node2>]


>>> for n in nodes:
...     print n, n.get_ancestors()
...
node0 []
node1 [<Node: node0>]
node2 [<Node: node0>]
node3 [<Node: node0>, <Node: node2>]
node4 [<Node: node0>, <Node: node2>]
node5 [<Node: node0>, <Node: node2>]
node6 [<Node: node0>, <Node: node2>]
node7 [<Node: node0>, <Node: node2>, <Node: node6>]
node8 [<Node: node0>, <Node: node2>, <Node: node6>]
node9 [<Node: node0>, <Node: node2>, <Node: node6>]
node10 [<Node: node0>, <Node: node2>, <Node: node6>]
node11 [<Node: node0>, <Node: node2>, <Node: node6>]
node12 [<Node: node0>, <Node: node2>, <Node: node6>]
node13 [<Node: node0>, <Node: node2>, <Node: node6>]
node14 [<Node: node0>, <Node: node2>, <Node: node6>]

Почему так много предков не так? Например, узел 10 должен иметь предков, (0,1,10)

Я что-то не так делаю или в django-mptt есть ошибки?

1 ответ

Решение

Я бы не сказал, что это глючит, но есть недоработка, о которой нужно знать.

Когда вы добавляете дочерний элемент к родительскому элементу, атрибуты дочернего дерева корректно обновляются с учетом MPTT lft, rght а также level ценности.

Однако django-mptt не обновляет версию родительского элемента, который у вас есть. Версия в базе данных обновлена, но копия в локальной переменной отсутствует (помните, что экземпляры модели Django не имеют идентификатора, поэтому не обновляйте, когда база данных или другие экземпляры, ссылающиеся на ту же строку базы данных, обновляются).

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

Решение заключается в перезагрузке родительского элемента из базы данных каждый раз, когда вы добавляете дочерний элемент:

for n in range(1,15):
    parent_pos = (n-1)/2
    parent = nodes[parent_pos]
    nodes[n].move_to(parent, 'last-child')
    nodes[n].save()
    nodes[parent_pos] = Node.objects.get(pk=parent.pk)
Другие вопросы по тегам