Opened 7 years ago
Last modified 18 months 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: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Ülgen Sarıkavak, Dmytro Litvinov | 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 (6)
comment:1 by , 7 years ago
| Has patch: | set |
|---|---|
| Patch needs improvement: | set |
| Triage Stage: | Unreviewed → Accepted |
| Type: | Bug → New feature |
comment:2 by , 6 years ago
| Version: | 2.2 → master |
|---|
comment:3 by , 6 years ago
comment:4 by , 4 years ago
I just found out that you can use dog_show.members.all().order_by('orderedmembership'). However, afaik, this (surprising!) feature is not documented, would be nice to add this to the docs.
comment:5 by , 20 months ago
| Cc: | added |
|---|
comment:6 by , 18 months ago
| Cc: | added |
|---|
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.orderinghas backward compatibility concerns as we have to decide how to deal withorderingdefined on both thethroughandtomodel. Should thethroughordering have precedence over thetoordering? Should they be merged together? We also have to make sure whatever we do regarding ordering translation honors the mechanisms in place to excludeMeta.orderingfrom aggregation as naively translating it into anorder_bycall 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.