Reputation: 4332
Django-rest-framework will has a SearchFilter
backend that will allow a single query against the searchable fields:
class OrganizationViewSet(viewsets.ModelViewSet):
queryset = Organization.objects.all()
serializer_class = OrganizationSerializer
pagination_class = CustomPagination
filter_backends = (filters.SearchFilter, DjangoFilterBackend)
filter_fields = ('sector', 'industry', 'marketplace')
search_fields = ('symbol',)
this way, when I query ...?search=AMZ
it will only return records with a non-sensitive match in the symbol
field.
If I add another element into the search_fields
tuple, it will look for this same search string in both.
Is there a way to define these search fields individually that will allow me to do something like:
?search_symbol=AMZ&search_name=Good
so that it looks for objects that have AMZ
in symbol
field and good
in name
field?
Upvotes: 3
Views: 2219
Reputation: 1167
You should look into using django-filter
instead. Might make your life easier.
https://django-filter.readthedocs.io/en/latest/index.html
Upvotes: 0
Reputation: 192
To achieve this you will need a custom filter backend extending the rest_framework.filters.SearchFilter
class. Specifically in the rest_framework.filters.SearchFilter
class there is a method get_search_terms
:
def get_search_terms(self, request):
"""
Search terms are set by a ?search=... query parameter,
and may be comma and/or whitespace delimited.
"""
params = request.query_params.get(self.search_param, '')
return params.replace(',', ' ').split()
We can override this method in our own CustomSearchFilter
class to take control of how you specify the search terms within the url, for example:
class CustomSearchFilter(SearchFilter):
search_field_prefix = "search_"
def get_search_terms(self, request):
# get search fields from the class
search_fields = getattr(request.resolver_match.func.view_class, 'search_fields', list())
params = []
# iterate over each query paramater in the url
for query_param in request.query_params:
# check if query paramater is a search paramater
if query_param.startswith(CustomSearchFilter.search_field_prefix):
# extrapolate the field name while handling cases where <CustomSearchFilter.search_field_prefix> is in the field name
field = CustomSearchFilter.search_field_prefix.join(
query_param.split(CustomSearchFilter.search_field_prefix)[1:]
)
# only apply search filter for fields that are in the views search_fields
if field in search_fields:
params.append(request.query_params.get(query_param, ''))
return params
Now replace the filters.SearchFilter
with your new CustomSearchFilter
in your views filter_backends
.
Hope this helps, I've written this without testing the code myself so let me know how you go!
Upvotes: 5