Skip to content

Commit 3ca0b15

Browse files
andialbrechttomchristie
authored andcommitted
Restore meta information for each search field. (#4298)
The meta information stored in opts needs to be restored for each search field. Otherwise it references the wrong model when an attribute of a related model comes before an attribute of the original model in search fields. This doesn't apply to m2m relations since must_call_distinct returns True in that case.
1 parent 48465a6 commit 3ca0b15

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

rest_framework/filters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ def must_call_distinct(self, queryset, search_fields):
174174
"""
175175
Return True if 'distinct()' should be used to query the given lookups.
176176
"""
177-
opts = queryset.model._meta
178177
for search_field in search_fields:
178+
opts = queryset.model._meta
179179
if search_field[0] in self.lookup_prefixes:
180180
search_field = search_field[1:]
181181
parts = search_field.split(LOOKUP_SEP)

tests/test_filters.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,47 @@ class AttributeModel(models.Model):
454454
label = models.CharField(max_length=32)
455455

456456

457+
class SearchFilterModelFk(models.Model):
458+
title = models.CharField(max_length=20)
459+
attribute = models.ForeignKey(AttributeModel)
460+
461+
462+
class SearchFilterFkSerializer(serializers.ModelSerializer):
463+
class Meta:
464+
model = SearchFilterModelFk
465+
fields = '__all__'
466+
467+
468+
class SearchFilterFkTests(TestCase):
469+
470+
def test_must_call_distinct(self):
471+
filter_ = filters.SearchFilter()
472+
prefixes = [''] + list(filter_.lookup_prefixes)
473+
for prefix in prefixes:
474+
self.assertFalse(
475+
filter_.must_call_distinct(
476+
SearchFilterModelFk._meta, ["%stitle" % prefix]
477+
)
478+
)
479+
self.assertFalse(
480+
filter_.must_call_distinct(
481+
SearchFilterModelFk._meta, ["%stitle" % prefix, "%sattribute__label" % prefix]
482+
)
483+
)
484+
485+
def test_must_call_distinct_restores_meta_for_each_field(self):
486+
# In this test case the attribute of the fk model comes first in the
487+
# list of search fields.
488+
filter_ = filters.SearchFilter()
489+
prefixes = [''] + list(filter_.lookup_prefixes)
490+
for prefix in prefixes:
491+
self.assertFalse(
492+
filter_.must_call_distinct(
493+
SearchFilterModelFk._meta, ["%sattribute__label" % prefix, "%stitle" % prefix]
494+
)
495+
)
496+
497+
457498
class SearchFilterModelM2M(models.Model):
458499
title = models.CharField(max_length=20)
459500
text = models.CharField(max_length=100)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy