Skip to content

Commit 152f83d

Browse files
authored
Merge branch 'master' into update-security-mail
2 parents 8cf52f1 + 7106502 commit 152f83d

File tree

8 files changed

+32
-16
lines changed

8 files changed

+32
-16
lines changed

CHANGELOG.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
Note that in line with [Django REST Framework policy](http://www.django-rest-framework.org/topics/release-notes/),
99
any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change.
1010

11-
## [Unreleased]
11+
## [4.2.0] - 2021-05-12
1212

1313
### Added
1414

@@ -25,16 +25,14 @@ 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-
28+
* Ensure default `included_resources` are considered when calculating prefetches.
29+
* Avoided error when using `include` query parameter on related urls (a regression since 4.1.0)
2930

3031
### Deprecated
3132

3233
* Deprecated default `format_type` argument of `rest_framework_json_api.utils.format_value`. Use `rest_framework_json_api.utils.format_field_name` or specify specifc `format_type` instead.
33-
* Deprecated `format_type` argument of `rest_framework_json_api.utils.format_link_segment`. Use `format_value` instead.
34+
* Deprecated `format_type` argument of `rest_framework_json_api.utils.format_link_segment`. Use `rest_framework_json_api.utils.format_value` instead.
3435

35-
### Fixed
36-
37-
* Avoided error when using `include` query parameter on related urls (a regression since 4.1.0)
3836

3937
## [4.1.0] - 2021-03-08
4038

example/tests/test_performance.py

Lines changed: 16 additions & 2 deletions
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)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
black==20.8b1
1+
black==21.4b2
22
flake8==3.9.1
33
flake8-isort==4.0.0
44
isort==5.8.0

requirements/requirements-testing.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
django-debug-toolbar==3.2.1
22
factory-boy==3.2.0
3-
Faker==8.1.0
3+
Faker==8.1.2
44
pytest==6.2.3
55
pytest-cov==2.11.1
66
pytest-django==4.2.0

rest_framework_json_api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22

33
__title__ = "djangorestframework-jsonapi"
4-
__version__ = "4.1.0"
4+
__version__ = "4.2.0"
55
__author__ = ""
66
__license__ = "BSD"
77
__copyright__ = ""

rest_framework_json_api/serializers.py

Lines changed: 1 addition & 1 deletion
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:

rest_framework_json_api/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ def get_resource_type_from_serializer(serializer):
326326

327327

328328
def get_included_resources(request, serializer=None):
329-
""" Build a list of included resources. """
329+
"""Build a list of included resources."""
330330
include_resources_param = request.query_params.get("include") if request else None
331331
if include_resources_param:
332332
return include_resources_param.split(",")

rest_framework_json_api/views.py

Lines changed: 7 additions & 3 deletions
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)
@@ -79,10 +81,12 @@ def get_queryset(self, *args, **kwargs):
7981

8082
class AutoPrefetchMixin(object):
8183
def get_queryset(self, *args, **kwargs):
82-
""" This mixin adds automatic prefetching for OneToOne and ManyToMany fields. """
84+
"""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)