Skip to content

Commit

Permalink
fixed bug when moving MP_Nodes, patched by Matt Hoskins, fixes bug dj…
Browse files Browse the repository at this point in the history
  • Loading branch information
tabo committed Mar 21, 2011
1 parent 1c60581 commit 2df093b
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 5 deletions.
3 changes: 2 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

Release 1.6X (XXX XX, 2010)
Release 1.6X (XXX XX, 2011)
---------------------------

* Revamped admin interface for MP and NS trees, supporting drag&drop to reorder
Expand All @@ -14,6 +14,7 @@ Release 1.6X (XXX XX, 2010)
* Added tox support
* Fixed the test suite to run in Python 2.4
* Fixed drag&drop bug in the admin (fixed by jmbarbier)
* Fixed a bug when moving MP_Nodes (fixed by Matt Hoskins)

Release 1.61 (Jul 24, 2010)
---------------------------
Expand Down
44 changes: 40 additions & 4 deletions treebeard/mp_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,39 @@ def _move_add_sibling_aux(cls, pos, newpos, newdepth, target, siblings,

newpath = cls._get_path(target.path, newdepth, newpos)

for node in siblings.reverse():
# If the move is amongst siblings and is to the left and there
# are siblings to the right of its new position then to be on
# the safe side we temporarily dump it on the end of the list
tempnewpath = None
if movebranch and len(oldpath) == len(newpath):
parentoldpath = cls._get_basepath(oldpath,
(len(oldpath) / cls.steplen) - 1)
parentnewpath = cls._get_basepath(newpath, newdepth - 1)
if (parentoldpath == parentnewpath and siblings and
newpath < oldpath):
last = target.get_last_sibling()
basenum = cls._get_lastpos_in_path(last.path)
tempnewpath = cls._get_path(newpath, newdepth, basenum + 2)
stmts.append(cls._get_sql_newpath_in_branches(oldpath,
tempnewpath))

# Optimisation to only move siblings which need moving
# (i.e. if we've got holes, allow them to compress)
movesiblings = []
priorpath = newpath
for node in siblings:
# If the path of the node is already greater than the path
# of the previous node it doesn't need shifting
if node.path > priorpath:
break
# It does need shifting, so add to the list
movesiblings.append(node)
# Calculate the path that it would be moved to, as that's
# the next "priorpath"
priorpath = cls._inc_path(node.path)
movesiblings.reverse()

for node in movesiblings:
# moving the siblings (and their branches) at the right of the
# related position one step to the right
sql, vals = cls._get_sql_newpath_in_branches(node.path,
Expand All @@ -772,8 +804,12 @@ def _move_add_sibling_aux(cls, pos, newpos, newdepth, target, siblings,
target.path = vals[0] + target.path[len(vals[0]):]
if movebranch:
# node to move
stmts.append(cls._get_sql_newpath_in_branches(oldpath,
newpath))
if tempnewpath:
stmts.append(cls._get_sql_newpath_in_branches(tempnewpath,
newpath))
else:
stmts.append(cls._get_sql_newpath_in_branches(oldpath,
newpath))
return oldpath, newpath

def _fix_move_to_child(self, pos, target, newdepth):
Expand Down Expand Up @@ -864,7 +900,7 @@ def _get_sql_newpath_in_branches(cls, oldpath, newpath):

sql2 = ["path=%s" % (sqlpath, )]
vals = [newpath, len(oldpath) + 1]
if (len(oldpath) != len(newpath) and
if (len(oldpath) != len(newpath) and
cls.get_database_engine() != 'mysql'):
# when using mysql, this won't update the depth and it has to be
# done in another query
Expand Down
31 changes: 31 additions & 0 deletions treebeard/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,37 @@ def _multi_move_sorted(self):
(4, 1, u'fgh', 2, 0)]
self.assertEqual(self.got(), expected)

def _multi_move_sortedsibling(self):
# https://bitbucket.org/tabo/django-treebeard/issue/27
self.sorted_model.add_root(val1=3, val2=3, desc='zxy')
self.sorted_model.add_root(val1=1, val2=4, desc='bcd')
self.sorted_model.add_root(val1=2, val2=5, desc='zxy')
self.sorted_model.add_root(val1=3, val2=3, desc='abc')
self.sorted_model.add_root(val1=4, val2=1, desc='fgh')
self.sorted_model.add_root(val1=3, val2=3, desc='abc')
self.sorted_model.add_root(val1=2, val2=2, desc='qwe')
self.sorted_model.add_root(val1=3, val2=2, desc='vcx')
root_nodes = self.sorted_model.get_root_nodes()
target = root_nodes[0]
for node in root_nodes[1:]:

# because raw queries don't update django objects
node = self.sorted_model.objects.get(pk=node.id)
target = self.sorted_model.objects.get(pk=target.id)

node.val1 = node.val1 - 2
node.save()
node.move(target, 'sorted-sibling')
expected = [(0, 2, u'qwe', 1, 0),
(0, 5, u'zxy', 1, 0),
(1, 2, u'vcx', 1, 0),
(1, 3, u'abc', 1, 0),
(1, 3, u'abc', 1, 0),
(1, 3, u'zxy', 1, 0),
(1, 4, u'bcd', 1, 0),
(2, 1, u'fgh', 1, 0)]
self.assertEqual(self.got(), expected)


class TestMP_TreeAlphabet(TestCase):

Expand Down

0 comments on commit 2df093b

Please sign in to comment.