1

我将在接下来的几天推出一个使用 Django MPTT 来管理分层数据的应用程序。MPTT 提供了一个名为rebuild的函数,该函数重建给定模型可用的所有树,并被调用为 such TreeNodes.objects.rebuild()。如您所见,该命令是在模型上调用的,而不是在模型实例上调用的。必须在将节点插入树后调用此命令。

对于 Django MPTT 0.6(尚未正式发布),实现了partial_rebuild命令,它只会重建给定的树。

虽然在本地测试多达 10 棵树,但它根本没有性能问题,但我担心我的数据库中有 100 棵树,我正在调用rebuild命令(这将重建所有 100 棵树),这可能是一个重要的性能问题。

有谁有使用该rebuild命令的经验吗?

4

1 回答 1

3

备查..

objects.rebuild() 仅在某些特殊情况下才需要。通常 mptt 仅通过设置节点的父 id 来正确设置节点的左右值。文档中也提到了这一点

我遇到了未正确设置左右值的问题,因为我保存了新节点!之前!我重置了其他已经存在的兄弟姐妹的位置值。当为具有元属性order_insertion_by集的树插入新节点时,必须首先重置所有兄弟节点的 order_insertion_by 值,然后保存新节点。这样 mptt 能够正确地重新计算左右值。

请参阅下面的(简化)示例:

模型.py

class Node(MPTTModel):
    """
    Representation of a single node
    """
    name = models.CharField(max_length=200)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='%(app_label)s_%(class)s_children')
    position = models.PositiveIntegerField(max_length=10) #for nodes on the same hierarchy level we have to define the position in which they are displayed 

    class MPTTMeta:
        order_insertion_by = ['position']

视图.py

new_node = Node(name="new node", parent=parent_node, position=1)
update_node_positions(new_node, 1) #routine to update the node positions
new_node.save()

更新节点位置

def update_node_positions(node, mode):
    """
    Procedure to update the node positions
    Three different modes available:
        1 = insert node
        2 = update position, parent stays the same
        3 = update position and change parent
        4 = trashed
    """

    if mode == 1 or mode==3:
        #if node has been inserted at the beginning
        if node.position == 1:
            node.get_siblings().update(position=F('position') + 1)
        #if node has been inserted not at beginning and not at the last position
        elif node.position != node.get_siblings().count() + 1:
            #update positions of siblings right of node by one
            node.get_siblings().filter(position__gte=node.position).update(position=F('position') + 1)
        if mode == 3:
            #since we removed the node from a parent, we have to decrement the positions of the former siblings right of the node by one
            if node._original_parent is not None:
                #do updates only for nodes which had a parent before. will not be executed for root nodes
                node._original_parent.get_children().filter(position__gt=node._original_position).update(position=F('position') - 1)
    if mode == 2:
        #if old position is left of new position -> decrement position by 1 for nodes which have position <= node.position AND > node.original_position
        if node.position > node._original_position:
            node.get_siblings().filter(Q(position__lte=node.position) & Q(position__gt=node._original_position)).update(position=F('position') - 1)
        #if old position is right of new position -> increment position by 1 for nodes which have position >= node.position AND < node.original_position 
        if node.position < node._original_position:
            node.get_siblings().filter(Q(position__gte=node.position) & Q(position__lt=node._original_position)).update(position=F('position') + 1)
    if mode == 4:
        #decrement position by 1 for nodes which have position > node.position
        node.get_siblings().filter(Q(position__gt=node.position)).update(position=F('position') - 1)
于 2013-05-15T14:56:55.173 回答