Skip to content

Commit fbb4b03

Browse files
Prefetch default included resources (#900)
Co-authored-by: Oliver Sauder <[email protected]>
1 parent a5df955 commit fbb4b03

File tree

4 files changed

+24
-5
lines changed

4 files changed

+24
-5
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ any parts of the framework not mentioned in the documentation should generally b
2525
OrderViewSet.as_view({'get': 'retrieve_related'}),
2626
name='order-related'),
2727
```
28+
* Ensure default `included_resources` are considered when calculating prefetches.
2829

2930

3031
### Deprecated

Diff for: example/tests/test_performance.py

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django.utils import timezone
22
from rest_framework.test import APITestCase
33

4-
from example.factories import CommentFactory
4+
from example.factories import CommentFactory, EntryFactory
55
from example.models import Author, Blog, Comment, Entry
66

77

@@ -36,6 +36,7 @@ def setUp(self):
3636
)
3737
self.comment = Comment.objects.create(entry=self.first_entry)
3838
CommentFactory.create_batch(50)
39+
EntryFactory.create_batch(50)
3940

4041
def test_query_count_no_includes(self):
4142
"""We expect a simple list view to issue only two queries.
@@ -49,7 +50,7 @@ def test_query_count_no_includes(self):
4950
self.assertEqual(len(response.data["results"]), 25)
5051

5152
def test_query_count_include_author(self):
52-
"""We expect a list view with an include have three queries:
53+
"""We expect a list view with an include have five queries:
5354
5455
1. Primary resource COUNT query
5556
2. Primary resource SELECT
@@ -70,3 +71,16 @@ def test_query_select_related_entry(self):
7071
with self.assertNumQueries(2):
7172
response = self.client.get("/comments?include=writer&page[size]=25")
7273
self.assertEqual(len(response.data["results"]), 25)
74+
75+
def test_query_prefetch_uses_included_resources(self):
76+
"""We expect a list view with `included_resources` to have three queries:
77+
78+
1. Primary resource COUNT query
79+
2. Primary resource SELECT
80+
3. Comments prefetched
81+
"""
82+
with self.assertNumQueries(3):
83+
response = self.client.get(
84+
"/entries?fields[entries]=comments&page[size]=25"
85+
)
86+
self.assertEqual(len(response.data["results"]), 25)

Diff for: rest_framework_json_api/serializers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def validate_path(serializer_class, field_path, path):
137137
validate_path(this_included_serializer, new_included_field_path, path)
138138

139139
if request and view:
140-
included_resources = get_included_resources(request)
140+
included_resources = get_included_resources(request, self)
141141
for included_field_name in included_resources:
142142
included_field_path = included_field_name.split(".")
143143
if "related_field" in view.kwargs:

Diff for: rest_framework_json_api/views.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ def get_prefetch_related(self, include):
6363
def get_queryset(self, *args, **kwargs):
6464
qs = super(PreloadIncludesMixin, self).get_queryset(*args, **kwargs)
6565

66-
included_resources = get_included_resources(self.request)
66+
included_resources = get_included_resources(
67+
self.request, self.get_serializer_class()
68+
)
6769
for included in included_resources + ["__all__"]:
6870

6971
select_related = self.get_select_related(included)
@@ -82,7 +84,9 @@ def get_queryset(self, *args, **kwargs):
8284
""" This mixin adds automatic prefetching for OneToOne and ManyToMany fields. """
8385
qs = super(AutoPrefetchMixin, self).get_queryset(*args, **kwargs)
8486

85-
included_resources = get_included_resources(self.request)
87+
included_resources = get_included_resources(
88+
self.request, self.get_serializer_class()
89+
)
8690

8791
for included in included_resources + ["__all__"]:
8892
# If include was not defined, trying to resolve it automatically

0 commit comments

Comments
 (0)