0

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.

With MPTTMeta (broken) Without MPTTMeta (working)

Saqib Ali
  • 11,931
  • 41
  • 133
  • 272
  • 1
    This looks like https://github.com/django-mptt/django-mptt/issues/320 – craigds Jan 11 '15 at 20:15
  • Craig, what is the definition of "bulk create"? Does what I'm doing above count as bulk-creation? – Saqib Ali Jan 12 '15 at 00:33
  • 1
    I believe that refers to modifying multiple nodes at once. The alternative being: changing one node, then re-fetching its value from the database before modifying a second node (as you might do if each node was changed via a web request) – craigds Jan 12 '15 at 04:07

1 Answers1

2

I've just committed a fix for this issue in django-mptt. Please test it! Cheers

craigds
  • 2,072
  • 14
  • 25