【问题标题】:Django-mptt completely buggy or am I doing it wrong?Django-mptt 完全错误还是我做错了?
【发布时间】:2011-01-10 07:21:36
【问题描述】:

我正在尝试使用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 中有错误?

【问题讨论】:

    标签: django mptt django-mptt


    【解决方案1】:

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

    当您将子级添加到父级时,子级的树属性会使用 MPTT 特定的 lftrghtlevel 值正确更新。

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

    【讨论】:

    • 非常感谢您的回答。我想我不会在我的情况下使用 mptt 并尝试 PostgreSQL 支持的“WITH RECURSIVE”。
    • 我几分钟前在另一个网站上发现了这一点,但您的解释是最简洁的,并确认我理解正确。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    • 2010-09-13
    相关资源
    最近更新 更多