mirror of
https://github.com/django/django.git
synced 2025-11-17 10:43:25 +00:00
Fix crash when Meta.ordering contains expressions in parent
Skip expressions in Meta.ordering during recursive ordering resolution to prevent TypeError when ordering by related models. Regression test added for ordering by ForeignKey to such models.
This commit is contained in:
parent
8dd5877f58
commit
e432ec4a3b
3 changed files with 87 additions and 1 deletions
|
|
@ -704,6 +704,16 @@ class SQLCompiler:
|
|||
not be) and column name for ordering by the given 'name' parameter.
|
||||
The 'name' is of the form 'field1__field2__...__fieldN'.
|
||||
"""
|
||||
# If name is an expression (e.g., OrderBy or F().asc() from Meta.ordering),
|
||||
# we can't process it through find_ordering_name as it's not a simple field name.
|
||||
# Expressions from Meta.ordering are meant for direct use in the model's own queries,
|
||||
# not for recursive processing when ordering by a ForeignKey.
|
||||
# Simply skip them to avoid crashes.
|
||||
if hasattr(name, 'resolve_expression'):
|
||||
# Skip expressions entirely - they're not applicable when recursively
|
||||
# processing related model ordering.
|
||||
return []
|
||||
|
||||
name, order = get_order_dir(name, default_order)
|
||||
descending = order == 'DESC'
|
||||
pieces = name.split(LOOKUP_SEP)
|
||||
|
|
|
|||
|
|
@ -59,3 +59,24 @@ class Reference(models.Model):
|
|||
|
||||
class Meta:
|
||||
ordering = ('article',)
|
||||
|
||||
|
||||
class ChildArticle(Article):
|
||||
"""
|
||||
Child model that inherits Article's Meta.ordering which contains expressions.
|
||||
"""
|
||||
class Meta:
|
||||
pass
|
||||
|
||||
|
||||
class RelatedToArticleWithExpression(models.Model):
|
||||
"""
|
||||
This model has a ForeignKey to Article (which has expressions in Meta.ordering)
|
||||
and orders by that relation. This tests the bug where expressions in parent
|
||||
model's Meta.ordering crash when processing the related ordering.
|
||||
"""
|
||||
article = models.ForeignKey(Article, models.CASCADE)
|
||||
name = models.CharField(max_length=100)
|
||||
|
||||
class Meta:
|
||||
ordering = ('article',)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@ from django.db.models.functions import Upper
|
|||
from django.test import TestCase
|
||||
from django.utils.deprecation import RemovedInDjango31Warning
|
||||
|
||||
from .models import Article, Author, OrderedByFArticle, Reference
|
||||
from .models import (
|
||||
Article, Author, ChildArticle, OrderedByFArticle, Reference,
|
||||
RelatedToArticleWithExpression,
|
||||
)
|
||||
|
||||
|
||||
class OrderingTests(TestCase):
|
||||
|
|
@ -471,3 +474,55 @@ class OrderingTests(TestCase):
|
|||
)
|
||||
with self.assertRaisesMessage(RemovedInDjango31Warning, msg):
|
||||
list(Article.objects.values('author').annotate(Count('headline')))
|
||||
|
||||
def test_related_ordering_with_expression_in_parent(self):
|
||||
"""
|
||||
Ordering by a ForeignKey to a model with Meta.ordering containing
|
||||
expressions (like OrderBy or F().asc()) should not crash.
|
||||
Regression test for #XXXXX.
|
||||
"""
|
||||
# Create test data
|
||||
a1 = Article.objects.create(
|
||||
headline="Test Article 1",
|
||||
pub_date=datetime(2020, 1, 1),
|
||||
author=self.author_1
|
||||
)
|
||||
a2 = Article.objects.create(
|
||||
headline="Test Article 2",
|
||||
pub_date=datetime(2020, 1, 2),
|
||||
author=self.author_2
|
||||
)
|
||||
|
||||
r1 = RelatedToArticleWithExpression.objects.create(article=a1, name="Related 1")
|
||||
r2 = RelatedToArticleWithExpression.objects.create(article=a2, name="Related 2")
|
||||
|
||||
# This should not crash with: TypeError: 'OrderBy' object is not subscriptable
|
||||
# The bug occurred because find_ordering_name didn't handle OrderBy expressions
|
||||
# from Meta.ordering when recursively processing related model ordering
|
||||
queryset = RelatedToArticleWithExpression.objects.all()
|
||||
list(queryset) # Force evaluation
|
||||
|
||||
# Verify the queryset can be evaluated multiple times
|
||||
self.assertEqual(queryset.count(), 2)
|
||||
|
||||
def test_child_inherits_parent_ordering_with_expressions(self):
|
||||
"""
|
||||
A child model that inherits Meta.ordering with expressions from its
|
||||
parent should handle ordering correctly.
|
||||
"""
|
||||
# Create test data
|
||||
ChildArticle.objects.create(
|
||||
headline="Child Article 1",
|
||||
pub_date=datetime(2020, 1, 1),
|
||||
author=self.author_1
|
||||
)
|
||||
ChildArticle.objects.create(
|
||||
headline="Child Article 2",
|
||||
pub_date=datetime(2020, 1, 2),
|
||||
author=self.author_2
|
||||
)
|
||||
|
||||
# This should not crash
|
||||
queryset = ChildArticle.objects.all()
|
||||
list(queryset) # Force evaluation
|
||||
self.assertEqual(queryset.count(), 2)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue