Added new filter - SearchFieldFilter

Added new Filter to allow the client choose the specific fields he wish to search for
(usually very good for grid tables where the client search on each column)
This commit is contained in:
Oz Bar Shalom 2018-03-07 08:55:22 +02:00 committed by GitHub
parent d2994e0596
commit 80320d015d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -306,3 +306,55 @@ class DjangoObjectPermissionsFilter(BaseFilterBackend):
else:
extra = {}
return get_objects_for_user(user, permission, queryset, **extra)
class SearchFieldFilter(SearchFilter):
# The URL query parameter used for the search on specific field.
# Use this filter to let the client choose the specific search field
# Example: ?search__name=x&search__last_name=y
search_param = api_settings.SEARCH_PARAM + '__'
lookup_prefixes = {
'^': 'istartswith',
'=': 'iexact',
'@': 'search',
'$': 'iregex',
}
def get_search_terms(self, request):
"""
Search terms are set by the user as a suffix after the ?search__FIELDNAME=... query parameter,
and may be comma and/or whitespace delimited.
"""
params = [(key.replace(self.search_param, ''), request.query_params[key]) for
key in request.query_params.keys()
if key.startswith(self.search_param)]
return params
def filter_queryset(self, request, queryset, view):
search_terms = self.get_search_terms(request)
if not search_terms:
return queryset
orm_lookups = [
self.construct_search(six.text_type(search_term[0]))
for search_term in search_terms
]
base = queryset
conditions = []
for search_term in search_terms:
queries = [
models.Q(**{orm_lookup: search_term[1]})
for orm_lookup in orm_lookups
]
conditions.append(reduce(operator.or_, queries))
queryset = queryset.filter(reduce(operator.and_, conditions))
if self.must_call_distinct(queryset, [search_term[0] for search_term in search_terms]):
# Filtering against a many-to-many field requires us to
# call queryset.distinct() in order to avoid duplicate items
# in the resulting queryset.
# We try to avoid this if possible, for performance reasons.
queryset = distinct(queryset, base)
return queryset