2010-01-28 6 views
7

Ich versuche django-mptt mit sehr wenig Glück zu verwenden. Dies ist mit Python2.5, Windows, Sqlite3, Django 1.2pre, Django-Mptt neuesten von Svn.Django-Mptt komplett Buggy oder mache ich es falsch?

Der Code:

Modell:

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) 

Setup:

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

Dieser einen Baum mit einer Wurzel erstellen sollte und zwei von jedem Nicht-Blattknoten hängen Kinder ab.

Jetzt beginnt der Spaß:

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

Warum sind so viele der Vorfahren nicht in Ordnung? Zum Beispiel sollte Knoten 10 Vorfahren haben, (0,1,10)

Mache ich etwas falsch oder gibt es Bugs in Django-Mptt?

Antwort

14

Ich würde nicht sagen, es ist fehlerhaft, aber es gibt eine Frage, die Sie beachten müssen.

Wenn Sie einem übergeordneten Element ein untergeordnetes Element hinzufügen, werden die Baumattribute des untergeordneten Elements ordnungsgemäß mit den MPTT-spezifischen Werten lft, rght und level aktualisiert.

Allerdings tut django-mptt nicht aktualisieren Sie die Version des übergeordneten, die Sie halten. Die Version in der Datenbank wird aktualisiert, die Kopie in Ihrer lokalen Variablen jedoch nicht. Denken Sie daran, dass Django-Modellinstanzen keine Identität aufweisen. Aktualisieren Sie sie daher nicht, wenn die Datenbank oder andere Instanzen auf dieselbe Datenbankzeile verweisen).

Das bedeutet, dass das nächste untergeordnete Objekt, das Sie dem übergeordneten Objekt hinzufügen, falsche linke und rechte Werte erhält. Wenn Sie anschließend das übergeordnete Element speichern, werden auch die falschen Werte angezeigt.

Die Lösung ist die übergeordnete aus der Datenbank jedes Mal, wenn ein Kind in das neu zu laden:

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

Vielen Dank für diese Antwort. Ich schätze, ich werde in meinem Fall kein mpt verwenden und "WITH RECURSIVE" ausprobieren, was von PostgreSQL unterstützt wird. – guettli

+0

Ich habe das vor ein paar Minuten auf einer anderen Seite herausgefunden, aber Ihre Erklärung war die prägnanteste und bestätigt, dass ich das richtig verstanden habe. Vielen Dank – Gattster

Verwandte Themen