Skip to content

Commit caa943f

Browse files
committed
Merged PreloadIncludesMixin into AutoPreloadMixin, test
1 parent c81c682 commit caa943f

File tree

3 files changed

+32
-19
lines changed

3 files changed

+32
-19
lines changed

example/tests/test_performance.py

+10
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,13 @@ def test_query_count_include_author(self):
5656
with self.assertNumQueries(5):
5757
response = self.client.get('/comments?include=author&page[size]=25')
5858
self.assertEqual(len(response.data['results']), 25)
59+
60+
def test_query_select_related_entry(self):
61+
""" We expect a list view with an include have three queries:
62+
63+
1. Primary resource COUNT query
64+
2. Primary resource SELECT + SELECT RELATED writer(author) and bio
65+
"""
66+
with self.assertNumQueries(2):
67+
response = self.client.get('/comments?include=writer&page[size]=25')
68+
self.assertEqual(len(response.data['results']), 25)

example/views.py

+3
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ class AuthorViewSet(ModelViewSet):
184184
class CommentViewSet(ModelViewSet):
185185
queryset = Comment.objects.all()
186186
serializer_class = CommentSerializer
187+
select_for_includes = {
188+
'writer': ['author__bio']
189+
}
187190
prefetch_for_includes = {
188191
'__all__': [],
189192
'author': ['author__bio', 'author__entries'],

rest_framework_json_api/views.py

+19-19
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class PrefetchForIncludesHelperMixin(object):
3535

3636
def __init__(self, *args, **kwargs):
3737
warnings.warn("PrefetchForIncludesHelperMixin is deprecated. "
38-
"Use PreloadIncludesMixin instead",
38+
"Use AutoPreloadMixin instead",
3939
DeprecationWarning)
4040
super(PrefetchForIncludesHelperMixin, self).__init__(*args, **kwargs)
4141

@@ -70,7 +70,7 @@ class MyViewSet(viewsets.ModelViewSet):
7070
return qs
7171

7272

73-
class PreloadIncludesMixin(object):
73+
class AutoPreloadMixin(object):
7474
"""
7575
This mixin provides a helper attributes to select or prefetch related models
7676
based on the include specified in the URL.
@@ -91,29 +91,31 @@ class MyViewSet(viewsets.ModelViewSet):
9191
'author': ['author', 'author__authorbio'],
9292
}
9393
"""
94-
def get_queryset(self):
95-
qs = super(PreloadIncludesMixin, self).get_queryset()
96-
97-
includes = self.request.GET.get('include', '').split(',') + ['__all__']
98-
99-
if hasattr(self, 'select_for_includes'):
100-
selects = [self.select_for_includes.get(inc) for inc in includes]
101-
qs = qs.select_related(*selects)
10294

103-
if hasattr(self, 'prefetch_for_includes'):
104-
prefetches = [self.prefetch_for_includes.get(inc) for inc in includes]
105-
qs = qs.prefetch_related(*prefetches)
106-
107-
return qs
95+
def get_select_related(self, include):
96+
return getattr(self, 'select_for_includes', {}).get(include, None)
10897

98+
def get_prefetch_related(self, include):
99+
return getattr(self, 'prefetch_for_includes', {}).get(include, None)
109100

110-
class AutoPreloadMixin(object):
111101
def get_queryset(self, *args, **kwargs):
112102
""" This mixin adds automatic prefetching for OneToOne and ManyToMany fields. """
113103
qs = super(AutoPreloadMixin, self).get_queryset(*args, **kwargs)
114104
included_resources = get_included_resources(self.request)
115105

116-
for included in included_resources:
106+
for included in included_resources + ['__all__']:
107+
# Custom defined "select_related" and "prefetch_related" is a priority
108+
select_related = self.get_select_related(included)
109+
if select_related is not None:
110+
qs = qs.select_related(*select_related)
111+
continue
112+
113+
prefetch_related = self.get_prefetch_related(included)
114+
if prefetch_related is not None:
115+
qs = qs.prefetch_related(*prefetch_related)
116+
continue
117+
118+
# If include was not defined, trying to resolve it automatically
117119
included_model = None
118120
levels = included.split('.')
119121
level_model = qs.model
@@ -241,14 +243,12 @@ def get_related_instance(self):
241243

242244

243245
class ModelViewSet(AutoPreloadMixin,
244-
PreloadIncludesMixin,
245246
RelatedMixin,
246247
viewsets.ModelViewSet):
247248
pass
248249

249250

250251
class ReadOnlyModelViewSet(AutoPreloadMixin,
251-
PreloadIncludesMixin,
252252
RelatedMixin,
253253
viewsets.ReadOnlyModelViewSet):
254254
pass

0 commit comments

Comments
 (0)