Opened 6 months ago

Last modified 6 weeks ago

#30460 new New feature

ManyToMany relationships with a custom `through` do not respect Meta.ordering on the intermediary model

Reported by: Ryan Petrello Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

ManyToManyFields that specify an intermediary model with a custom Meta.ordering do not inherit that ordering.

class Dog(models.Model):
    pass


class OrderedMembership(models.Model):

    class Meta:
        ordering = ('position',)

    dog = models.ForeignKey('Dog', models.CASCADE)
    winner = models.ForeignKey('Winner', models.CASCADE)
    position = models.PositiveIntegerField()


class Winner(models.Model):
    name = models.CharField(max_length=128)
    # OrderedMembership object defined as a class
    members = models.ManyToManyField(Dog, through=OrderedMembership)

lassie = Dog('Lassie')
fido = Dog('Fido')
rover = Dog('Rover')
dog_show = Winner(name='Dog Show')
OrderedMembership.objects.create(dog=lassie, winner=dog_show, position=3)
OrderedMembership.objects.create(dog=fido, winner=dog_show, position=2)
OrderedMembership.objects.create(dog=rover, winner=dog_show, position=1)

dog_show.members.all()   # <--- does not respect `OrderedMembership.position`


This means that if you want to create a custom M2M model that manages default order via some column on the M2M table:

https://github.com/ansible/awx/pull/3842/files#diff-ea6da88b8c0cd3fbf7858ae87933b296R995
https://github.com/gregmuellegger/django-sortedm2m/blob/b48481ebd1212f1af22a6a04d1c8372b5a837350/sortedm2m/fields.py#L41

...it doesn't work as you'd expect (the M2M relation falls back to natural database order - usually the primary key of the target model).

Change History (2)

comment:1 Changed 6 months ago by Simon Charette

Has patch: set
Patch needs improvement: set
Triage Stage: UnreviewedAccepted
Type: BugNew feature

I wouldn't say this is actually a bug as many-to-many field managers have always supported ordering on their referenced model

Adding support for through._meta.ordering has backward compatibility concerns as we have to decide how to deal with ordering defined on both the through and to model. Should the through ordering have precedence over the toordering? Should they be merged together? We also have to make sure whatever we do regarding ordering translation honors the mechanisms in place to exclude Meta.ordering from aggregation as naively translating it into an order_by call will bypass the checks added in 1b1f64ee5a78cc217fead52cbae23114502cf564 for #14357.

In my opinion the resulting ordering should be through._meta.ordering + to._meta.ordering. This might require a django-developers thread to gather feedback though.

Accepting the ticket on the basis that it seems like a feature that should be supported but the current PR requires significant adjustments first.

comment:2 Changed 6 weeks ago by Asif Saifuddin Auvi

Version: 2.2master
Note: See TracTickets for help on using tickets.
Back to Top