#coding: utf-8
import re
import inspect
import operator
from django.db.models import Q, query
import rest_framework
class QSimpleFilter(rest_framework.filters.BaseFilterBackend):
'''
Специальные методы определяются по регэкспу. Они должны возвращать Q.
Фильтры объединяются через AND или OR в зависимости от флага combine.
'''
method_regexps = [r'^filter_by_(.*)']
combine = 'AND'
def special_methods(self):
'Должны возвращать Q объекты'
for regexp in self.method_regexps:
for attr in dir(self):
item = getattr(self, attr)
match = re.search(regexp, attr)
if not match:
continue
if inspect.ismethod(item):
yield (match.group(1), item)
def filter_queryset(self, request, queryset, view):
GET = dict(request.GET.items())
q_filters = [method(queryset, GET.get(param))
for param, method in self.special_methods()
if param in GET]
if q_filters:
assert self.combine in ('AND', 'OR')
operation = operator.and_ if self.combine == 'AND' \
else operator.or_
try:
queryset = queryset.filter(reduce(operation, q_filters))
except:
queryset = query.EmptyQuerySet()
return queryset