My Django application has a model called Treenode which implements a tree by subclassing the MPTTModel
(Version 0.6.1). The model is as follows:
from mptt.models import MPTTModel, TreeForeignKey
class Treenode(MPTTModel):
name = models.CharField(max_length=255)
parent = TreeForeignKey('self', null=True, blank=True)
class MPTTMeta:
order_insertion_by = ['name']
def __unicode__(self):
return "%s (#%s)" % (self.name, self.pk)
Now look what happens when I start creating instances of this model:
>>> a = Treenode(name="S", parent=None,); a.save()
>>> b = Treenode(name="B", parent=None,); b.save()
>>> c = Treenode(name="C", parent=a,); c.save()
>>> print "b.id = %s; b.name = %s; b.get_children() = %s; b.get_descendants() = %s" % (b.id, b.name, b.get_children(), b.get_descendants())
b.id = 2; b.name = B; b.get_children() = []; b.get_descendants() = []
>>> x = Treenode.objects.get(name="B")
>>> print "x.id = %s; x.name = %s; x.get_children() = %s; x.get_descendants() = %s" % (x.id, x.name, x.get_children(), x.get_descendants())
x.id = 2; x.name = B; x.get_children() = []; x.get_descendants() = [<Category: C (#3)>]
Do you see the bug? x
is the same instance as b
-- just retrieved from the database. But MPTT wrongly reports that instance C
is a descendant of x
. It's not!
I experimented with this mightily to isolate and identify the issue. I found that if I change the name attribute of instance a
from "S" to "A", the problem vanishes. I also found that if I remove the nested MPTTMeta
class from the model, the problem vanishes. This indicates to me that there is a problem with MPTTMeta's order_insertion_by code. Can anyone confirm this or know if there is a fix out there?
As added evidence, I have included screenshots of the database table for Treenode when I had MPTTMeta (Broken) and after I removed MPTTMeta (Working) for comparison purposes.