2010-01-28 67 views
7

我试图用django-mptt运气很少。这是Python2.5,windows,sqlite3,Django 1.2pre,django-mptt最新来自svn。Django-mptt完全越野车或我做错了吗?

代码:

型号:

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中存在错误?

回答

14

我不会说它是越野车,但有一个你需要注意的问题。

将子项添加到父项时,子项的树属性使用特定于MPTT的lft,rghtlevel值正确更新。

但是,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) 
+0

非常感谢您对这个答案。我想我不会在我的情况下使用mptt,并尝试使用PostgreSQL支持的“WITH RECURSIVE”。 – guettli 2014-06-18 07:20:22

+0

几分钟前我在另一个网站上发现了这一点,但您的解释是最简洁的,并确认我正确理解这一点。谢谢 – Gattster 2014-10-19 05:21:39