Skip to content

Commit 34ee962

Browse files
committed
Allows searching with SearchFilter in annotated fields
Fixes #6094
1 parent dd19a44 commit 34ee962

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

rest_framework/filters.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ def must_call_distinct(self, queryset, search_fields):
7979
search_field = search_field[1:]
8080
parts = search_field.split(LOOKUP_SEP)
8181
for part in parts:
82+
if isinstance(queryset, models.QuerySet) and part in queryset.query.annotations:
83+
# This field is annotated
84+
continue
8285
field = opts.get_field(part)
8386
if hasattr(field, 'get_path_info'):
8487
# This field is a relation, update opts to follow the relation

tests/test_filters.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,40 @@ class SearchListView(generics.ListAPIView):
304304
assert len(response.data) == 1
305305

306306

307+
class NumbersModel(models.Model):
308+
a = models.IntegerField()
309+
b = models.IntegerField()
310+
311+
312+
class NumbersSerializer(serializers.ModelSerializer):
313+
a_plus_b = serializers.IntegerField()
314+
315+
class Meta:
316+
model = NumbersModel
317+
fields = ('a', 'b', 'a_plus_b')
318+
319+
320+
class SearchFilterAnnotatedFieldTests(TestCase):
321+
@classmethod
322+
def setUpTestData(cls):
323+
NumbersModel.objects.create(a=1, b=2)
324+
NumbersModel.objects.create(a=3, b=4)
325+
326+
def test_search_in_annotated_field(self):
327+
class SearchListView(generics.ListAPIView):
328+
queryset = NumbersModel.objects.annotate(
329+
a_plus_b=models.F('a') + models.F('b')).all()
330+
serializer_class = NumbersSerializer
331+
filter_backends = (filters.SearchFilter,)
332+
search_fields = ('a_plus_b',)
333+
334+
view = SearchListView.as_view()
335+
request = factory.get('/', {'search': '3'})
336+
response = view(request)
337+
assert len(response.data) == 1
338+
assert response.data[0]['a_plus_b'] == 3
339+
340+
307341
class OrderingFilterModel(models.Model):
308342
title = models.CharField(max_length=20, verbose_name='verbose title')
309343
text = models.CharField(max_length=100)

0 commit comments

Comments
 (0)