diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index a0d2d028cd..59b40ebfc9 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1622,6 +1622,11 @@ class Query(BaseExpression): return target_clause def add_filtered_relation(self, filtered_relation, alias): + if "." in alias: + raise ValueError( + "FilteredRelation doesn't support aliases with periods " + "(got %r)." % alias + ) self.check_alias(alias) filtered_relation.alias = alias lookups = dict(get_children_from_q(filtered_relation.condition)) diff --git a/tests/filtered_relation/tests.py b/tests/filtered_relation/tests.py index 0fce8b092a..4847d1f04b 100644 --- a/tests/filtered_relation/tests.py +++ b/tests/filtered_relation/tests.py @@ -211,6 +211,19 @@ class FilteredRelationTests(TestCase): str(queryset.query), ) + def test_period_forbidden(self): + msg = ( + "FilteredRelation doesn't support aliases with periods (got 'book.alice')." + ) + with self.assertRaisesMessage(ValueError, msg): + Author.objects.annotate( + **{ + "book.alice": FilteredRelation( + "book", condition=Q(book__title__iexact="poem by alice") + ) + } + ) + def test_multiple(self): qs = ( Author.objects.annotate( diff --git a/tests/ordering/tests.py b/tests/ordering/tests.py index 530a27920e..30da025875 100644 --- a/tests/ordering/tests.py +++ b/tests/ordering/tests.py @@ -15,7 +15,6 @@ from django.db.models import ( Value, ) from django.db.models.functions import Length, Upper -from django.db.utils import DatabaseError from django.test import TestCase from .models import ( @@ -408,13 +407,19 @@ class OrderingTests(TestCase): self.assertNotEqual(qs[0].headline, "Backdated") relation = FilteredRelation("author") - qs2 = Article.objects.annotate(**{crafted: relation}).order_by(crafted) - with self.assertRaises(DatabaseError): + msg = ( + "FilteredRelation doesn't support aliases with periods " + "(got 'ordering_article.pub_date')." + ) + with self.assertRaisesMessage(ValueError, msg): + qs2 = Article.objects.annotate(**{crafted: relation}).order_by(crafted) # Before, unlike F(), which causes ordering expressions to be # replaced by ordinals like n in ORDER BY n, these were ordered by # pub_date instead of author. # The Article model orders by -pk, so sorting on author will place # first any article by author2 instead of the backdated one. + # This assertion is reachable if FilteredRelation.__init__() starts + # supporting periods in aliases in the future. self.assertNotEqual(qs2[0].headline, "Backdated") def test_order_by_pk(self):