diff --git a/rest_framework/filters.py b/rest_framework/filters.py index 213182dad..366577519 100644 --- a/rest_framework/filters.py +++ b/rest_framework/filters.py @@ -85,7 +85,7 @@ class SearchFilter(BaseFilterBackend): search_field = search_field[1:] # Annotated fields do not need to be distinct if isinstance(queryset, models.QuerySet) and search_field in queryset.query.annotations: - return False + continue parts = search_field.split(LOOKUP_SEP) for part in parts: field = opts.get_field(part) diff --git a/tests/test_filters.py b/tests/test_filters.py index 30cedc7d7..e69537666 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -406,6 +406,21 @@ class SearchFilterAnnotatedFieldTests(TestCase): assert len(response.data) == 1 assert response.data[0]['title_text'] == 'ABCDEF' + def test_must_call_distinct_subsequent_m2m_fields(self): + f = filters.SearchFilter() + + queryset = SearchFilterModelM2M.objects.annotate( + title_text=Upper( + Concat(models.F('title'), models.F('text')) + ) + ).all() + + # Sanity check that m2m must call distinct + assert f.must_call_distinct(queryset, ['attributes']) + + # Annotated field should not prevent m2m must call distinct + assert f.must_call_distinct(queryset, ['title_text', 'attributes']) + class OrderingFilterModel(models.Model): title = models.CharField(max_length=20, verbose_name='verbose title')