在接下来的几天里,我将推出一个使用Django MPTT管理分层数据的应用程序。MPTT提供了一个名为rebuild的函数,它可以重新构建给定模型可用的所有树,并被称为TreeNodes.objects.rebuild()
。如您所见,该命令是在模型上调用的,而不是在模型的实例上调用的。此命令必须在将节点插入到树中后调用。
对于Django MPTT 0.6 (还没有正式的released),实现了一个partial_rebuild命令,它只会重新构建给定的树。
虽然在本地测试多达10棵树完全没有性能问题,但我担心当我的数据库中有100棵树,并且我调用rebuild
命令(它将重建所有100棵树)时,这可能是一个严重的性能问题。
有谁有使用rebuild
命令的经验吗?
发布于 2013-05-15 14:56:55
以备将来参考..
只有在某些特殊情况下才需要使用objects.rebuild()。通常,mptt只需设置节点的父id,即可正确设置节点的左值和右值。docs中也提到了这一点
我遇到了一个没有正确设置左、右值的问题,因为我保存了新节点,!之前!我重置了另一个已经存在的同级的位置值。在为设置了元属性order_insertion_by
的树插入新节点时,必须首先重置所有同级的order_insertion_by值,然后保存新节点。这样,mptt就能够正确地重新计算左侧和右侧的值。
参见下面我的(简化)示例:
models.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']
views.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()
update_node_positions
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)
https://stackoverflow.com/questions/16516032
复制