summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNilesh Kumar Pahari <nileshpahari@protonmail.com>2026-02-05 17:23:33 -0500
committerJacob Walls <jacobtylerwalls@gmail.com>2026-02-06 15:45:45 -0500
commit6380e3f01e10f815de8c0223e3fd4bacb69f3808 (patch)
treedcfad4cd02903d58575b7b3a787238a397ddc82f
parent087bb9e8f3478d53f12b1737af865992af17c5f2 (diff)
Fixed #36644 -- Enabled empty order_by() to avoid pk ordering by first()/last().
-rw-r--r--django/db/models/query.py4
-rw-r--r--tests/get_earliest_or_latest/models.py8
-rw-r--r--tests/get_earliest_or_latest/tests.py30
3 files changed, 39 insertions, 3 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index afb3aac5cb..76d0f449a6 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1158,7 +1158,7 @@ class QuerySet(AltersData):
def first(self):
"""Return the first object of a query or None if no match is found."""
- if self.ordered:
+ if self.ordered or not self.query.default_ordering:
queryset = self
else:
self._check_ordering_first_last_queryset_aggregation(method="first")
@@ -1171,7 +1171,7 @@ class QuerySet(AltersData):
def last(self):
"""Return the last object of a query or None if no match is found."""
- if self.ordered:
+ if self.ordered or not self.query.default_ordering:
queryset = self.reverse()
else:
self._check_ordering_first_last_queryset_aggregation(method="last")
diff --git a/tests/get_earliest_or_latest/models.py b/tests/get_earliest_or_latest/models.py
index bbf2075d36..91725865b1 100644
--- a/tests/get_earliest_or_latest/models.py
+++ b/tests/get_earliest_or_latest/models.py
@@ -21,6 +21,14 @@ class Comment(models.Model):
likes_count = models.PositiveIntegerField()
+class OrderedArticle(models.Model):
+ headline = models.CharField(max_length=100)
+ pub_date = models.DateField()
+
+ class Meta:
+ ordering = ["headline"]
+
+
# Ticket #23555 - model with an intentionally broken QuerySet.__iter__ method.
diff --git a/tests/get_earliest_or_latest/tests.py b/tests/get_earliest_or_latest/tests.py
index 49c803b73a..793fb12bb9 100644
--- a/tests/get_earliest_or_latest/tests.py
+++ b/tests/get_earliest_or_latest/tests.py
@@ -1,9 +1,10 @@
from datetime import datetime
+from unittest.mock import patch
from django.db.models import Avg
from django.test import TestCase
-from .models import Article, Comment, IndexErrorArticle, Person
+from .models import Article, Comment, IndexErrorArticle, OrderedArticle, Person
class EarliestOrLatestTests(TestCase):
@@ -265,3 +266,30 @@ class TestFirstLast(TestCase):
qs.first()
with self.assertRaisesMessage(TypeError, msg % "last"):
qs.last()
+
+ def test_first_last_empty_order_by_has_no_pk_ordering(self):
+ Article.objects.create(
+ headline="Article 1",
+ pub_date=datetime(2006, 9, 10),
+ expire_date=datetime(2056, 9, 11),
+ )
+
+ qs = Article.objects.order_by()
+ with patch.object(type(qs), "order_by") as mock_order_by:
+ qs.first()
+ mock_order_by.assert_not_called()
+ qs.last()
+ mock_order_by.assert_not_called()
+
+ def test_first_last_empty_order_by_clears_default_ordering(self):
+ OrderedArticle.objects.create(
+ headline="Article 1",
+ pub_date=datetime(2006, 9, 10),
+ )
+
+ qs = OrderedArticle.objects.order_by()
+ with patch.object(type(qs), "order_by") as mock_order_by:
+ qs.first()
+ mock_order_by.assert_not_called()
+ qs.last()
+ mock_order_by.assert_not_called()