[Django] #36644: Enable using an empty order_by() to disable implicit primary key ordering in first()

8 views
Skip to first unread message

Django

unread,
Oct 7, 2025, 6:58:13 AMOct 7
to django-...@googlegroups.com
#36644: Enable using an empty order_by() to disable implicit primary key ordering
in first()
-------------------------------------+-------------------------------------
Reporter: Lily | Type: New
| feature
Status: new | Component: Database
| layer (models, ORM)
Version: dev | Severity: Normal
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
As discussed in https://github.com/django/new-features/issues/71, update
the interaction between `order_by` and `first` to enable this behaviour:

{{{
# Existing
MyModel.objects.first() # first, ordered by `pk`
MyModel.objects.order_by("pk").first() # as above
MyModel.objects.order_by("name").first() # first, ordered by `name`

# New
MyModel.objects.order_by().first() # first, but in whatever order the
database returns it
}}}

This will interact with
[https://docs.djangoproject.com/en/5.2/ref/models/options/#django.db.models.Options.ordering
default orderings (`Meta.ordering`)], which will need some careful
handling.
--
Ticket URL: <https://code.djangoproject.com/ticket/36644>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Oct 7, 2025, 7:35:38 AMOct 7
to django-...@googlegroups.com
#36644: Enable using an empty order_by() to disable implicit primary key ordering
in first()
-------------------------------------+-------------------------------------
Reporter: Lily | Owner: (none)
Type: New feature | Status: new
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Simon Charette):

* stage: Unreviewed => Accepted

--
Ticket URL: <https://code.djangoproject.com/ticket/36644#comment:1>

Django

unread,
Oct 7, 2025, 6:08:28 PMOct 7
to django-...@googlegroups.com
#36644: Enable using an empty order_by() to disable implicit primary key ordering
in first()
-------------------------------------+-------------------------------------
Reporter: Lily | Owner: Mridul
Type: New feature | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mridul):

* owner: (none) => Mridul
* status: new => assigned

--
Ticket URL: <https://code.djangoproject.com/ticket/36644#comment:2>

Django

unread,
Oct 8, 2025, 2:52:24 AMOct 8
to django-...@googlegroups.com
#36644: Enable using an empty order_by() to disable implicit primary key ordering
in first()
-------------------------------------+-------------------------------------
Reporter: Lily | Owner: Mridul
Type: New feature | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* cc: Jake Howard (added)

Comment:

For folks checking the forum thread, when Tom Carrick summarized the
options discussed [https://github.com/django/new-
features/issues/71#issuecomment-3325381421 here], this was "option 2", to
which I did not see specific objections afterward.
----
> This will interact with ​default orderings (`Meta.ordering`), which will
need some careful handling.

I think that looks like this:

{{{#!diff
diff --git a/django/db/models/query.py b/django/db/models/query.py
index b404fd1875..4d1218ea89 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1135,9 +1135,13 @@ class QuerySet(AltersData):

def first(self):
"""Return the first object of a query or None if no match is
found."""
+ # RemovedInDjango70Warning: replace with:
+ # if self.ordered or not self.query.default_ordering:
if self.ordered:
queryset = self
else:
+ if not self.query.default_ordering:
+ warnings.warn(..., RemovedInDjango70Warning,
skip_file_prefixes=django_file_prefixes())
self._check_ordering_first_last_queryset_aggregation(method="first")
queryset = self.order_by("pk")
for obj in queryset[:1]:
@@ -1148,9 +1152,13 @@ class QuerySet(AltersData):

def last(self):
"""Return the last object of a query or None if no match is
found."""
+ # RemovedInDjango70Warning: replace with:
+ # if self.ordered or not self.query.default_ordering:
if self.ordered:
queryset = self.reverse()
else:
+ if not self.query.default_ordering:
+ warnings.warn(..., RemovedInDjango70Warning,
skip_file_prefixes=django_file_prefixes())
self._check_ordering_first_last_queryset_aggregation(method="last")
queryset = self.order_by("-pk")
for obj in queryset[:1]:
diff --git a/tests/queries/test_qs_combinators.py
b/tests/queries/test_qs_combinators.py
index e329d0c4f0..79cfb78dd7 100644
--- a/tests/queries/test_qs_combinators.py
+++ b/tests/queries/test_qs_combinators.py
@@ -416,7 +416,7 @@ class QuerySetSetOperationTests(TestCase):
base_qs = Author.objects.order_by()
qs1 = base_qs.filter(name="a1")
qs2 = base_qs.filter(name="a2")
- self.assertEqual(qs1.union(qs2).first(), a1)
+ self.assertEqual(qs1.union(qs2).order_by("pk").first(), a1)

def test_union_multiple_models_with_values_list_and_order(self):
reserved_name = ReservedName.objects.create(name="rn1", order=0)
}}}

I think this will need a deprecation (notice the edited test). We will be
enforcing some more explicitness for users who must to clear an ordering
for the sake of doing a union but then need to add it back to retain the
prior behavior of `first()`, but I think that trade-off is worth it.
--
Ticket URL: <https://code.djangoproject.com/ticket/36644#comment:3>

Django

unread,
6:37 AM (5 hours ago) 6:37 AM
to django-...@googlegroups.com
#36644: Enable using an empty order_by() to disable implicit primary key ordering
in first()
-------------------------------------+-------------------------------------
Reporter: Lily | Owner: Nilesh
| Pahari
Type: New feature | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Nilesh Pahari):

* owner: Mridul => Nilesh Pahari

--
Ticket URL: <https://code.djangoproject.com/ticket/36644#comment:4>
Reply all
Reply to author
Forward
0 new messages