0

I'm using django-mptt 0.4.2 and have trouble with one of my data trees.

Here is the tree as seen in mysql;

mysql> select id, lft,rght,level from my_object where tree_id=30613;
+-------+-----+------+-------+
| id    | lft | rght | level |
+-------+-----+------+-------+
| 89919 |   1 |   10 |     0 | 
| 89924 |  10 |   11 |     1 | 
| 89930 |   6 |    9 |     1 | 
| 90401 |   2 |    5 |     1 | 
| 90406 |   3 |    4 |     2 | 
| 90407 |   7 |    8 |     2 | 
+-------+-----+------+-------+

In my Python shell it looks the same:

>>> obj = MyObject.objects.filter(tree_id=30613)
>>> for o in obj:
...     print "%5d %2d %2d %1d" % (o.id, o.lft, o.rght, o.level)
... 
89919  1 10 0
89924 10 11 1
89930  6  9 1
90401  2  5 1
90406  3  4 2
90407  7  8 2

The problem is when I use the .get_descendants() method from django.mptt:

>>> parent_node = MyObject.objects.get(id=89919)
>>> descendants = parent_node.get_descendants()
>>> for o in descendants:
...     print "%5d %2d %2d %1d" % (o.id, o.lft, o.rght, o.level)
... 
90401  2  5 1
90406  3  4 2
89930  6  9 1
90407  7  8 2


>>> print descendants.query # Formatted for readability
SELECT * FROM `my_obj` 
WHERE (
    `my_obj`.`lft` <= 9  
    AND `my_obj`.`lft` >= 2  
    AND `my_obj`.`tree_id` = 30613 
) ORDER BY `my_obj`.`tree_id` ASC, `my_obj`.`lft` ASC

Why doesn't django-mptt retrieve all the descendants?

manji
  • 47,442
  • 5
  • 96
  • 103
Hobhouse
  • 15,463
  • 12
  • 35
  • 43

1 Answers1

2

The tree is in an inaccurate state:

parentnode:89919[left=1, right=10] can not contain childnode:89924[left=10, right=11]

You can see it in the query, it's searching for child nodes with left >= 2 (paren_left+1) and <= 9 (parent_right-1)

You might want to rebuild the tree to obtain correct results.

Have you used move_to recently? Look at the note here:move_to(target, position='first-child'), may be it's related.

The same problem may arise with inset_at and it's due to fact that when using insert_at or move_to you supply a parent node that is updated in the database but not in memory, so you have to get a fresh copy of the parent after each one of these actions.

More info here:insert_node using last-child does not work correctly

manji
  • 47,442
  • 5
  • 96
  • 103
  • I have not used move_to(), only insert_at(), with transactions activated. Any idea what may cause the tree to be inaccurate? Perhaps a race condition? – Hobhouse Apr 04 '11 at 15:17
  • it's the same problem as `move_to`. I updated my answer with a link to this specific issue in django-mptt. – manji Apr 04 '11 at 15:41