Opened 6 years ago
Last modified 6 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
ManyToManyField
s 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 , 6 years ago
Has patch: | set |
---|---|
Patch needs improvement: | set |
Triage Stage: | Unreviewed → Accepted |
Type: | Bug → New feature |
comment:2 by , 5 years ago
Version: | 2.2 → master |
---|
comment:3 by , 5 years ago
comment:4 by , 3 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 , 8 months ago
Cc: | added |
---|
comment:6 by , 6 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.ordering
has backward compatibility concerns as we have to decide how to deal withordering
defined on both thethrough
andto
model. Should thethrough
ordering have precedence over theto
ordering? Should they be merged together? We also have to make sure whatever we do regarding ordering translation honors the mechanisms in place to excludeMeta.ordering
from aggregation as naively translating it into anorder_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.