mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-16 19:41:06 +03:00
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.
This commit is contained in:
parent
48465a667a
commit
3ca0b15b17
|
@ -174,8 +174,8 @@ class SearchFilter(BaseFilterBackend):
|
||||||
"""
|
"""
|
||||||
Return True if 'distinct()' should be used to query the given lookups.
|
Return True if 'distinct()' should be used to query the given lookups.
|
||||||
"""
|
"""
|
||||||
opts = queryset.model._meta
|
|
||||||
for search_field in search_fields:
|
for search_field in search_fields:
|
||||||
|
opts = queryset.model._meta
|
||||||
if search_field[0] in self.lookup_prefixes:
|
if search_field[0] in self.lookup_prefixes:
|
||||||
search_field = search_field[1:]
|
search_field = search_field[1:]
|
||||||
parts = search_field.split(LOOKUP_SEP)
|
parts = search_field.split(LOOKUP_SEP)
|
||||||
|
|
|
@ -454,6 +454,47 @@ class AttributeModel(models.Model):
|
||||||
label = models.CharField(max_length=32)
|
label = models.CharField(max_length=32)
|
||||||
|
|
||||||
|
|
||||||
|
class SearchFilterModelFk(models.Model):
|
||||||
|
title = models.CharField(max_length=20)
|
||||||
|
attribute = models.ForeignKey(AttributeModel)
|
||||||
|
|
||||||
|
|
||||||
|
class SearchFilterFkSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = SearchFilterModelFk
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class SearchFilterFkTests(TestCase):
|
||||||
|
|
||||||
|
def test_must_call_distinct(self):
|
||||||
|
filter_ = filters.SearchFilter()
|
||||||
|
prefixes = [''] + list(filter_.lookup_prefixes)
|
||||||
|
for prefix in prefixes:
|
||||||
|
self.assertFalse(
|
||||||
|
filter_.must_call_distinct(
|
||||||
|
SearchFilterModelFk._meta, ["%stitle" % prefix]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.assertFalse(
|
||||||
|
filter_.must_call_distinct(
|
||||||
|
SearchFilterModelFk._meta, ["%stitle" % prefix, "%sattribute__label" % prefix]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_must_call_distinct_restores_meta_for_each_field(self):
|
||||||
|
# In this test case the attribute of the fk model comes first in the
|
||||||
|
# list of search fields.
|
||||||
|
filter_ = filters.SearchFilter()
|
||||||
|
prefixes = [''] + list(filter_.lookup_prefixes)
|
||||||
|
for prefix in prefixes:
|
||||||
|
self.assertFalse(
|
||||||
|
filter_.must_call_distinct(
|
||||||
|
SearchFilterModelFk._meta, ["%sattribute__label" % prefix, "%stitle" % prefix]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SearchFilterModelM2M(models.Model):
|
class SearchFilterModelM2M(models.Model):
|
||||||
title = models.CharField(max_length=20)
|
title = models.CharField(max_length=20)
|
||||||
text = models.CharField(max_length=100)
|
text = models.CharField(max_length=100)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user