feincms3 icon indicating copy to clipboard operation
feincms3 copied to clipboard

TreeAdmin displaying odd ordering with more than 1 root node

Open kronok opened this issue 9 years ago • 2 comments

model

class Step(CTENode):
    description = models.CharField(max_length=75, null=True, blank=True)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, limit_choices_to=step_choices, null=True, blank=True)
    object_id = GfkLookupField('content_type', null=True, blank=True)
    content_object = GenericForeignKey('content_type', 'object_id')
    is_active = models.BooleanField(verbose_name="Active", default=True, help_text="If not active, subscribers will still be allowed to move to this step, but this step won't run until it's active. Consider this a good way to 'hold' subscribers on this step. Note: Step children won't run either.")
    position = models.PositiveIntegerField(db_index=True, editable=False, default=0)

    _cte_node_path = 'cte_path'
    _cte_node_order_by = ('position',)

admin

class StepAdmin(TreeAdmin):
    model = Step
    generic_raw_id_fields = ['content_object']
    raw_id_fields = ('parent',)
    list_display = ('indented_title', 'move_column')

issue

>>> root_one = Step.objects.create(description='root_one')
>>> root_one_middle = Step.objects.create(description='root_one_middle', parent=root_one)
>>> root_one_bottom = Step.objects.create(description='root_one_bottom', parent=root_one_middle)

root_one

That looks as expected. Let's add another root node.

>>> root_two = Step.objects.create(description='root_two')
>>> root_two_middle = Step.objects.create(description='root_two_middle', parent=root_two)
>>> root_two_bottom = Step.objects.create(description='root_two_bottom', parent=root_two_middle)

root_two It only seems to look good with 1 root node. Everything gets displayed properly even when adding multiple children all over the place, but as soon as another root node gets in, it gets wonky. Only happens in Admin. Likely has something to do with TreeAdmin's get_ordering method, but I'm curious if you're able to re-create this with your Page model.

kronok avatar Sep 23 '16 19:09 kronok

Yes, I've seen something similar just today. I had to set position to a depth first ordering across trees (that is, all position values of the second trees are bigger than all position values of the first tree)

That shouldn't be necessary though, and I'm not completely sure why it was (yet). Pointers would be very much appreciated, but I'll certainly (have to) solve this issue soonish.

matthiask avatar Sep 23 '16 20:09 matthiask

I have been thinking on-and-off about this issue and now have a good idea why this happens. The probable cause is that the position value of both root nodes were the same. This would also explain why it happened to me as well, since I renamed the MPTT lft field to position (which means that both root nodes had a position value of 1).

The code in feincms3.pages.AbstractPage.save ensures that new nodes always have a bigger position value than any other nodes with the same parent. This invariant does not hold of course when nodes are created without the position assignment resp. when trees are converted from mptt.

matthiask avatar Oct 03 '16 06:10 matthiask