From 720ef7a867eab1491f5789fe39b3431a498b2b89 Mon Sep 17 00:00:00 2001 From: Peter DeVita Date: Fri, 17 Jan 2025 13:22:24 -0500 Subject: [PATCH] [5.2.x] Fixed #36109 -- Fixed RecursionError when stacking FilteredRelation joins. Backport of 8eca4077f60fa0705ecfd9437c9ceaeef7a3808b from main. --- AUTHORS | 1 + django/db/models/sql/query.py | 2 ++ tests/filtered_relation/tests.py | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/AUTHORS b/AUTHORS index 9d8956bda0..0648241267 100644 --- a/AUTHORS +++ b/AUTHORS @@ -823,6 +823,7 @@ answer newbie questions, and generally made Django that much better: Petar Marić Pete Crosier peter@mymart.com + Peter DeVita Peter Sheats Peter van Kampen Peter Zsoldos diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 6fbf854e67..ddf6c891fa 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1946,6 +1946,8 @@ class Query(BaseExpression): reuse = can_reuse if join.m2m else None alias = self.join(connection, reuse=reuse) joins.append(alias) + if join.filtered_relation and can_reuse is not None: + can_reuse.add(alias) return JoinInfo(final_field, targets, opts, joins, path, final_transformer) def trim_joins(self, targets, joins, path): diff --git a/tests/filtered_relation/tests.py b/tests/filtered_relation/tests.py index cbf77752df..a9c6e00567 100644 --- a/tests/filtered_relation/tests.py +++ b/tests/filtered_relation/tests.py @@ -582,6 +582,28 @@ class FilteredRelationTests(TestCase): lambda x: (x.author, x.book_title, x.preferred_by_author_pk), ) + def test_three_level_nested_chained_relations(self): + borrower = Borrower.objects.create(name="Jenny") + Reservation.objects.create( + borrower=borrower, + book=self.book1, + state=Reservation.STOPPED, + ) + qs = Author.objects.annotate( + my_books=FilteredRelation("book"), + my_reserved_books=FilteredRelation( + "my_books__reservation", + condition=Q(my_books__reservation__state=Reservation.STOPPED), + ), + my_readers=FilteredRelation( + "my_reserved_books__borrower", + condition=Q(my_reserved_books__borrower=borrower), + ), + ) + self.assertSequenceEqual( + qs.filter(my_readers=borrower).values_list("name", flat=True), ["Alice"] + ) + def test_deep_nested_foreign_key(self): qs = ( Book.objects.annotate(