Browse Source

Fixed #35135 -- Made FilteredRelation raise ValueError on querysets as rhs.

Regression in 59f475470494ce5b8cbff816b1e5dafcbd10a3a3.
Nicolas Delaby 1 year ago
parent
commit
820c5f1bac
3 changed files with 25 additions and 0 deletions
  1. 10 0
      django/db/models/sql/query.py
  2. 5 0
      docs/releases/5.0.2.txt
  3. 10 0
      tests/filtered_relation/tests.py

+ 10 - 0
django/db/models/sql/query.py

@@ -91,6 +91,8 @@ def get_children_from_q(q):
 
 
 def get_child_with_renamed_prefix(prefix, replacement, child):
+    from django.db.models.query import QuerySet
+
     if isinstance(child, Node):
         return rename_prefix_from_q(prefix, replacement, child)
     if isinstance(child, tuple):
@@ -105,6 +107,14 @@ def get_child_with_renamed_prefix(prefix, replacement, child):
         child = child.copy()
         if child.name.startswith(prefix + LOOKUP_SEP):
             child.name = child.name.replace(prefix, replacement, 1)
+    elif isinstance(child, QuerySet):
+        # QuerySet may contain OuterRef() references which cannot work properly
+        # without repointing to the filtered annotation and will spawn a
+        # different JOIN. Always raise ValueError instead of providing partial
+        # support in other cases.
+        raise ValueError(
+            "Passing a QuerySet within a FilteredRelation is not supported."
+        )
     elif hasattr(child, "resolve_expression"):
         child = child.copy()
         child.set_source_expressions(

+ 5 - 0
docs/releases/5.0.2.txt

@@ -19,3 +19,8 @@ Bugfixes
 
 * Fixed a bug in Django 5.0 that caused a crash of ``Model.full_clean()`` on
   models with a ``GeneratedField`` (:ticket:`35127`).
+
+* Fixed a regression in Django 5.0 that caused a crash of
+  ``FilteredRelation()`` with querysets as right-hand sides (:ticket:`35135`).
+  ``FilteredRelation()`` now raises a ``ValueError`` on querysets as right-hand
+  sides.

+ 10 - 0
tests/filtered_relation/tests.py

@@ -828,6 +828,16 @@ class FilteredRelationTests(TestCase):
         ).filter(rel__isnull=True)
         self.assertSequenceEqual(qs, [])
 
+    def test_conditional_expression_does_not_support_queryset(self):
+        msg = "Passing a QuerySet within a FilteredRelation is not supported."
+        with self.assertRaisesMessage(ValueError, msg):
+            Author.objects.annotate(
+                poem_book=FilteredRelation(
+                    "book",
+                    condition=Q(book__in=Book.objects.filter(title__istartswith="a")),
+                ),
+            ).filter(poem_book__isnull=False)
+
 
 class FilteredRelationAggregationTests(TestCase):
     @classmethod