mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-02 19:40:13 +03:00
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:
parent
d2994e0596
commit
80320d015d
|
@ -306,3 +306,55 @@ class DjangoObjectPermissionsFilter(BaseFilterBackend):
|
||||||
else:
|
else:
|
||||||
extra = {}
|
extra = {}
|
||||||
return get_objects_for_user(user, permission, queryset, **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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user