Skip to content

Commit 2a0d0c6

Browse files
author
Ryan P Kilby
committed
Merge pull request #67 from rpkilby/refactor-related-queryset
Simplify RelatedFilter
2 parents 99a0b7e + 500a726 commit 2a0d0c6

File tree

3 files changed

+28
-30
lines changed

3 files changed

+28
-30
lines changed

rest_framework_filters/filters.py

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from __future__ import absolute_import
22
from __future__ import unicode_literals
33

4-
from collections import OrderedDict
54
from django.utils import six
65

76
from django_filters.filters import *
@@ -22,7 +21,6 @@ def _import_class(path):
2221
class RelatedFilter(ModelChoiceFilter):
2322
def __init__(self, filterset, *args, **kwargs):
2423
self.filterset = filterset
25-
# self.parent_relation = kwargs.get('parent_relation', None)
2624
return super(RelatedFilter, self).__init__(*args, **kwargs)
2725

2826
def filterset():
@@ -37,29 +35,11 @@ def fset(self, value):
3735
return locals()
3836
filterset = property(**filterset())
3937

40-
def get_filterset_subset(self, filter_names):
41-
"""
42-
Returns a FilterSet subclass that contains the subset of filters
43-
specified in `filter_names`. This is useful for creating FilterSets
44-
used across relationships, as it minimizes the deepcopy overhead
45-
incurred when instantiating the FilterSet.
46-
"""
47-
BaseFilterSet = self.filterset
48-
49-
class FilterSetSubset(BaseFilterSet):
50-
pass
51-
52-
FilterSetSubset.__name__ = str('%sSubset' % (BaseFilterSet.__name__))
53-
FilterSetSubset.base_filters = OrderedDict([
54-
(name, f)
55-
for name, f in six.iteritems(BaseFilterSet.base_filters)
56-
if name in filter_names
57-
])
58-
59-
return FilterSetSubset
60-
61-
def setup_filterset(self):
62-
self.extra['queryset'] = self.filterset._meta.model.objects.all()
38+
@property
39+
def field(self):
40+
# if no queryset is provided, default to the filterset's default queryset
41+
self.extra.setdefault('queryset', self.filterset._meta.model._default_manager.all())
42+
return super(RelatedFilter, self).field
6343

6444

6545
class AllLookupsFilter(Filter):

rest_framework_filters/filterset.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ def __init__(self, *args, **kwargs):
6666

6767
for name, filter_ in six.iteritems(self.filters.copy()):
6868
if isinstance(filter_, filters.RelatedFilter):
69-
filter_.setup_filterset()
70-
7169
# Add an 'isnull' filter to allow checking if the relation is empty.
7270
filter_name = "%s%sisnull" % (filter_.name, LOOKUP_SEP)
7371
if filter_name not in self.filters:
@@ -131,7 +129,7 @@ def get_filters(self):
131129

132130
# otherwise build and insert it into the cache
133131
if subset_class is None:
134-
subset_class = related_filter.get_filterset_subset(filter_names)
132+
subset_class = related_filter.filterset.get_subset(filter_names)
135133
self.cache_set(key, subset_class)
136134

137135
# initialize and copy filters
@@ -164,6 +162,26 @@ def get_filter_name(cls, param):
164162
if isinstance(f, filters.RelatedFilter):
165163
return related_param
166164

165+
@classmethod
166+
def get_subset(cls, filter_names):
167+
"""
168+
Returns a FilterSet subclass that contains the subset of filters
169+
specified in `filter_names`. This is useful for creating FilterSets
170+
used across relationships, as it minimizes the deepcopy overhead
171+
incurred when instantiating the FilterSet.
172+
"""
173+
class FilterSetSubset(cls):
174+
pass
175+
176+
FilterSetSubset.__name__ = str('%sSubset' % (cls.__name__))
177+
FilterSetSubset.base_filters = OrderedDict([
178+
(name, f)
179+
for name, f in six.iteritems(cls.base_filters)
180+
if name in filter_names
181+
])
182+
183+
return FilterSetSubset
184+
167185
def cache_key(self, filterset, filter_names):
168186
return '%sSubset-%s' % (filterset.__name__, '-'.join(sorted(filter_names)), )
169187

tests/test_filterset.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,9 +304,9 @@ def test_m2m_relation(self):
304304
titles = set([p.title for p in f])
305305
self.assertEqual(titles, set(["First post", "Second post"]))
306306

307-
def test_get_filterset_subset(self):
307+
def test_get_subset(self):
308308
related_filter = NoteFilterWithRelated.base_filters['author']
309-
filterset_class = related_filter.get_filterset_subset(['email'])
309+
filterset_class = related_filter.filterset.get_subset(['email'])
310310

311311
# ensure that the class name is useful when debugging
312312
self.assertEqual(filterset_class.__name__, 'UserFilterSubset')

0 commit comments

Comments
 (0)