Skip to content

Commit aa24389

Browse files
committed
Eliminate the need for overriding get_queryset() for filtering logic
1 parent 2fc13df commit aa24389

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

filters/decorators.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
def decorate_get_queryset(f):
3+
def decorated(self):
4+
queryset = f(self)
5+
query_params = self.request.query_params
6+
url_params = self.kwargs
7+
8+
# get queryset_filters from FiltersMixin
9+
queryset_filters = self.get_db_filters(url_params, query_params)
10+
11+
# This dict will hold filter kwargs to pass in to Django ORM calls.
12+
db_filters = queryset_filters['db_filters']
13+
14+
# This dict will hold exclude kwargs to pass in to Django ORM calls.
15+
db_excludes = queryset_filters['db_excludes']
16+
17+
return queryset.filter(**db_filters).exclude(**db_excludes)
18+
return decorated

filters/metaclasses.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from .decorators import decorate_get_queryset
2+
3+
4+
class MetaFiltersMixin(type):
5+
def __new__(cls, name, bases, dct):
6+
if 'get_queryset' in dct:
7+
dct['get_queryset'] = decorate_get_queryset(dct['get_queryset'])
8+
return super(MetaFiltersMixin, cls).__new__(cls, name, bases, dct)
9+
10+
def __setattr__(self, attr, val):
11+
if attr == 'get_queryset':
12+
val = decorate_get_queryset(val)
13+
return super(MetaFiltersMixin, self).__setattr__(attr, val)

filters/mixins.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from voluptuous import Invalid
33
from rest_framework.exceptions import ParseError
44

5+
from .metaclasses import MetaFiltersMixin
56
from .schema import base_query_params_schema
67

78

@@ -11,6 +12,7 @@ class FiltersMixin(object):
1112
filters by applying defined filters on generic
1213
queryset.
1314
'''
15+
__metaclass__ = MetaFiltersMixin
1416

1517
def __get_queryset_filters(self, query_params, *args, **kwargs):
1618
'''
@@ -87,3 +89,11 @@ def get_db_filters(self, url_params, query_params):
8789
'db_filters': db_filters,
8890
'db_excludes': db_excludes,
8991
}
92+
93+
def get_queryset(self):
94+
# Defined here to handle the case where the viewset
95+
# does not override get_queryset
96+
# (and hence the metaclass would not have been
97+
# able to decorate it with the filtering logic.)
98+
99+
return super(FiltersMixin, self).get_queryset()

0 commit comments

Comments
 (0)