mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-28 04:24:00 +03:00
Apply review commnents
This commit is contained in:
parent
5bdc44bc89
commit
854e22b6bc
|
@ -196,7 +196,7 @@ When in use, the browsable API will include a `SearchFilter` control:
|
||||||
|
|
||||||
![Search Filter](../img/search-filter.png)
|
![Search Filter](../img/search-filter.png)
|
||||||
|
|
||||||
The `SearchFilter` class will only be applied if the view has a `search_fields` attribute set. The `search_fields` attribute should be a list of names of text type fields on the model, such as `CharField` or `TextField`.
|
The `SearchFilter` class will only be applied if the view or `SearchFilter` class itself has a `search_fields` attribute set. The `search_fields` attribute should be a list of names of text type fields on the model, such as `CharField` or `TextField`.
|
||||||
|
|
||||||
from rest_framework import filters
|
from rest_framework import filters
|
||||||
|
|
||||||
|
@ -243,6 +243,21 @@ To dynamically change search fields based on request content, it's possible to s
|
||||||
return ['title']
|
return ['title']
|
||||||
return super().get_search_fields(view, request)
|
return super().get_search_fields(view, request)
|
||||||
|
|
||||||
|
To use use multiple filters in the same view, override `search_param` and `search_fields` attribute. Many filters can be applied simultaneously on the same view. For example, the following subclass will search on `title` if the query parameter `search_title` is used and search on `text` if the query parameter `search_title` is used:
|
||||||
|
|
||||||
|
from rest_framework import filters
|
||||||
|
|
||||||
|
class TitleSearchFilter(filters.SearchFilter):
|
||||||
|
search_param = 'search_title'
|
||||||
|
search_fields = ('$title', )
|
||||||
|
|
||||||
|
class TextSearchFilter(filters.SearchFilter):
|
||||||
|
search_param = 'search_text'
|
||||||
|
search_fields = ('$text', )
|
||||||
|
|
||||||
|
class SearchListView(generics.ListAPIView):
|
||||||
|
filter_backends = (TitleSearchFilter, TextSearchFilter)
|
||||||
|
|
||||||
For more details, see the [Django documentation][search-django-admin].
|
For more details, see the [Django documentation][search-django-admin].
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -52,8 +52,8 @@ class SearchFilter(BaseFilterBackend):
|
||||||
|
|
||||||
def get_search_fields(self, view, request):
|
def get_search_fields(self, view, request):
|
||||||
"""
|
"""
|
||||||
Search fields are obtained from the view, but the request is always
|
Search fields are obtained from the view / search backend, but the request is
|
||||||
passed to this method. Sub-classes can override this method to
|
always passed to this method. Sub-classes can override this method to
|
||||||
dynamically change the search fields based on request content.
|
dynamically change the search fields based on request content.
|
||||||
"""
|
"""
|
||||||
return getattr(view, 'search_fields', getattr(self, 'search_fields'))
|
return getattr(view, 'search_fields', getattr(self, 'search_fields'))
|
||||||
|
|
|
@ -36,7 +36,6 @@ class ListModelMixin:
|
||||||
"""
|
"""
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
|
||||||
page = self.paginate_queryset(queryset)
|
page = self.paginate_queryset(queryset)
|
||||||
if page is not None:
|
if page is not None:
|
||||||
serializer = self.get_serializer(page, many=True)
|
serializer = self.get_serializer(page, many=True)
|
||||||
|
|
|
@ -181,6 +181,44 @@ class SearchFilterTests(TestCase):
|
||||||
{'id': 3, 'title': 'zzz', 'text': 'cde'}
|
{'id': 3, 'title': 'zzz', 'text': 'cde'}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def test_search_with_filter_multiple(self):
|
||||||
|
class TitleSearchFilter(filters.SearchFilter):
|
||||||
|
search_param = 'search_title'
|
||||||
|
search_fields = ('$title', )
|
||||||
|
|
||||||
|
class TextSearchFilter(filters.SearchFilter):
|
||||||
|
search_param = 'search_text'
|
||||||
|
search_fields = ('$text', )
|
||||||
|
|
||||||
|
class SearchListView(generics.ListAPIView):
|
||||||
|
queryset = SearchFilterModel.objects.all()
|
||||||
|
serializer_class = SearchFilterSerializer
|
||||||
|
filter_backends = (TitleSearchFilter, TextSearchFilter)
|
||||||
|
|
||||||
|
view = SearchListView.as_view()
|
||||||
|
request = factory.get('/', {TitleSearchFilter.search_param: r'^z{3}$'})
|
||||||
|
response = view(request)
|
||||||
|
assert response.data == [
|
||||||
|
{'id': 3, 'title': 'zzz', 'text': 'cde'}
|
||||||
|
]
|
||||||
|
|
||||||
|
request = factory.get('/', {TextSearchFilter.search_param: r'^cde$'})
|
||||||
|
response = view(request)
|
||||||
|
assert response.data == [
|
||||||
|
{'id': 3, 'title': 'zzz', 'text': 'cde'}
|
||||||
|
]
|
||||||
|
|
||||||
|
request = factory.get('/', {
|
||||||
|
TitleSearchFilter.search_param: r'^(z{3}|z{2})$',
|
||||||
|
TextSearchFilter.search_param: r'^\w{3}$'
|
||||||
|
})
|
||||||
|
response = view(request)
|
||||||
|
assert response.data == [
|
||||||
|
{'id': 2, 'title': 'zz', 'text': 'bcd'},
|
||||||
|
{'id': 3, 'title': 'zzz', 'text': 'cde'}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_search_field_with_null_characters(self):
|
def test_search_field_with_null_characters(self):
|
||||||
view = generics.GenericAPIView()
|
view = generics.GenericAPIView()
|
||||||
request = factory.get('/?search=\0as%00d\x00f')
|
request = factory.get('/?search=\0as%00d\x00f')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user