2010-01-28 11 views
7

Estoy intentando usar django-mptt con muy poca suerte. Esto es con Python2.5, Windows, sqlite3, Django 1.2pre, django-mptt más reciente de svn.Django-mptt ¿Tiene errores o lo estoy haciendo mal?

El código:

modelo:

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) 

configuración:

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

Esto debería crear un árbol con una raíz y sus dos hijos colgando de cada nodo no hoja.

ahora comienza la diversión:

>>> 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>] 

¿Por qué son tan muchos de los antepasados ​​mal? Por ejemplo, el nodo 10 debería tener ancestros, (0,1,10)

¿Estoy haciendo algo mal o hay errores en django-mptt?

Respuesta

14

No diría que es un error, pero hay un problema que debes tener en cuenta.

Cuando agrega un elemento secundario a un elemento primario, los atributos de árbol del elemento secundario se actualizan correctamente con los valores lft, rght y level específicos de MPTT.

Sin embargo, django-mptt does not actualiza la versión del padre que tiene. La versión en la base de datos se actualiza, pero la copia en su variable local no (recuerde que las instancias del modelo Django no tienen identidad, por lo que no se actualizan cuando la base de datos u otras instancias que hacen referencia a la misma fila de la base de datos actualicen)

Esto significa que el siguiente elemento secundario que agregue al objeto principal obtendrá los valores incorrectos a la izquierda y a la derecha, y si posteriormente guarda el elemento primario, también tendrá los valores incorrectos.

La solución es volver a cargar la matriz de la base de datos cada vez que se agrega un niño:

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) 
+0

Muchas gracias por esta respuesta. Supongo que no usaré mptt en mi caso y probaré "WITH RECURSIVE" soportado por PostgreSQL. – guettli

+0

Lo descubrí hace unos minutos en otro sitio, pero tu explicación fue la más concisa y confirma que entiendo esto correctamente. Gracias – Gattster

Cuestiones relacionadas