django-polymorphic / django-polymorphic-tree

Polymorphic MPTT tree support for models
Other
171 stars 44 forks source link

Different types of models are created in the wrong order #87

Open samul-1 opened 1 year ago

samul-1 commented 1 year ago

Say I have the following models:

class BaseTreeNode(PolymorphicMPTTModel):
    parent = PolymorphicTreeForeignKey(
        "self",
        blank=True,
        null=True,
        related_name="children",
        on_delete=models.CASCADE,
    )

    class MPTTMeta:
        order_insertion_by = ["lft"]

class RooteNode(BaseTreeNode):
    pass

class NodeA(BaseTreeNode):
    pass

class NodeB(BaseTreeNode):
    pass

Let's say I create a RootNode r, then I create two NodeA instances, a1 and a2. If I try to list the children of r, the order will be a2, a1, as expected.

However, if I create an instance of NodeB, b1, the order will be a2, a1, b1, instead of the expected b1, a2, a1.

This seems to happen because of this line in django-mptt. The instruction:

queryset = (
      node.__class__._tree_manager.db_manager(node._state.db)
      .filter(filters)
      .order_by(*order_by)
)

is used inside of the get_ordered_insertion_target to get the siblings of the newly created node and determine the insertion position. However, when using inheritance on node models, this ends up only retrieving the siblings of the newly created node of its same type.

For example, this instruction, used in place of the offending one would cause the expected, correct behavior for the shown case:

queryset = (
     node.__class__.mro()[1]
    .objects.db_manager(node._state.db)
    .filter(filters)
    .order_by(*order_by)
)

Of course, something more sophisticated is needed in order to actually detect whether the model is inheriting from another abstract model or not.

Is there anything that can be done on django-polymorphic-tree's side to fix this?