mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-22 17:47:04 +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.
|
||||
"""
|
||||
opts = queryset.model._meta
|
||||
for search_field in search_fields:
|
||||
opts = queryset.model._meta
|
||||
if search_field[0] in self.lookup_prefixes:
|
||||
search_field = search_field[1:]
|
||||
parts = search_field.split(LOOKUP_SEP)
|
||||
|
|
|
@ -454,6 +454,47 @@ class AttributeModel(models.Model):
|
|||
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):
|
||||
title = models.CharField(max_length=20)
|
||||
text = models.CharField(max_length=100)
|
||||
|
|
Loading…
Reference in New Issue
Block a user