diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 995e89564d..01ff007eda 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -934,8 +934,14 @@ class Query: if (reuse is None or a in reuse) and j == join ] if reuse_aliases: - self.ref_alias(reuse_aliases[0]) - return reuse_aliases[0] + if join.table_alias in reuse_aliases: + reuse_alias = join.table_alias + else: + # Reuse the most recent alias of the joined table + # (a many-to-many relation may be joined multiple times). + reuse_alias = reuse_aliases[-1] + self.ref_alias(reuse_alias) + return reuse_alias # No reuse is possible, so we need a new alias. alias, _ = self.table_alias(join.table_name, create=True, filtered_relation=join.filtered_relation) diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py index 4fc7e6f047..c1073d6f41 100644 --- a/tests/annotations/tests.py +++ b/tests/annotations/tests.py @@ -569,3 +569,19 @@ class NonAggregateAnnotationTestCase(TestCase): Book.objects.annotate(is_book=True) with self.assertRaisesMessage(TypeError, msg % ', '.join([str(BooleanField()), 'True'])): Book.objects.annotate(BooleanField(), Value(False), is_book=True) + + def test_chaining_annotation_filter_with_m2m(self): + qs = Author.objects.filter( + name='Adrian Holovaty', + friends__age=35, + ).annotate( + jacob_name=F('friends__name'), + ).filter( + friends__age=29, + ).annotate( + james_name=F('friends__name'), + ).values('jacob_name', 'james_name') + self.assertCountEqual( + qs, + [{'jacob_name': 'Jacob Kaplan-Moss', 'james_name': 'James Bennett'}], + )