Opened 2 years ago

Last modified 2 years ago

#34130 closed Bug

order_by() has no effect on values()/values_list() — at Initial Version

Reported by: Michal Dabski Owned by: nobody
Component: Database layer (models, ORM) Version: 3.2
Severity: Normal Keywords: queryset, ordering, values, values_list
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I have encounteded a bug with a model that has default ordering. I am making a query with order_by() without parameters to avoid ordering and then use values() or values_list() to extract a subset of fields. The end result is an ordered queryset.

It appears that values() restores model's default ordering if called after order_by(), except if queryset is already ordered by cystom ordering (e.g. order_by('name')), in which case order_by is maintained.

Django 3.2.16

The model:

class Dashboard(models.Model):
    name = models.CharField(max_length=100)
    order = models.PositiveIntegerField(default=1)

    class Meta:
        ordering = 'order',

Note: it is important that the model defineds ordering

To reproduce issue:

# Queryset is ordered by default field as expected ✔
str(Dashboard.objects.all().values('name').ordered)
Out[44]: 'True'

# Queryset is not ordered after adding order_by() as expected ✔
str(Dashboard.objects.all().order_by().ordered)
Out[54]: 'False'

# adding values() call somehow restores default ordering. Expected behaviour is for QS to remain unordered ✖
str(Dashboard.objects.all().order_by().values('name').ordered)
Out[42]: 'True'

# placing order_by() after values() works as expected ✔
str(Dashboard.objects.all().values('name').order_by().ordered)
Out[48]: 'False'

In my case I am using order_by() to avoid using JOIN in the query when I know that order does not matter, but resulting query does make a join unbeknownst to me and makes the more complex ordered query.

The documentation for values/values_list and order_by does not appear to mention this behaviour so I am assuming it is not intentional.

Change History (0)

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