Skip to content

Commit 1fe3857

Browse files
committed
allow Prefetch objects to be used for prefetching
1 parent 21347ea commit 1fe3857

File tree

3 files changed

+13
-16
lines changed

3 files changed

+13
-16
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ db.sqlite3
44
*.py[cod]
55
__pycache__
66
env
7+
venv
78
.python-version
89

910
# C extensions

drf_sideloading/mixins.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from itertools import chain
77

8+
from django.db.models import Prefetch
89
from rest_framework.renderers import BrowsableAPIRenderer
910
from rest_framework.response import Response
1011
from rest_framework.serializers import ListSerializer
@@ -90,14 +91,11 @@ def get_sideloading_prefetches(self):
9091
cleaned_prefetches = {}
9192
for k, v in prefetches.items():
9293
if v is not None:
93-
if isinstance(v, list):
94-
cleaned_prefetches[k] = v
95-
elif isinstance(v, six.string_types):
96-
cleaned_prefetches[k] = [v]
97-
else:
98-
raise RuntimeError(
99-
"Sideloadable prefetch values must be presented either as a list or a string"
100-
)
94+
if not isinstance(v, list):
95+
v = [v]
96+
for vi in v:
97+
if not isinstance(vi, (six.string_types, Prefetch)):
98+
raise RuntimeError("Sideloadable prefetch values must be a list of strings or Prefetch objects")
10199
return cleaned_prefetches
102100

103101
def initialize_request(self, request, *args, **kwargs):

tests/test_products_api.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from __future__ import unicode_literals
55

6+
from django.db.models import Prefetch
67
from rest_framework.permissions import BasePermission
78
from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer
89
from rest_framework.settings import api_settings
@@ -388,19 +389,14 @@ class Meta:
388389
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
389390

390391
def test_correct_exception_raised(self):
391-
with self.assertRaises(RuntimeError) as cm:
392+
expected_error_message = "Sideloadable prefetch values must be a list of strings or Prefetch objects"
393+
with self.assertRaisesMessage(RuntimeError, expected_error_message):
392394
self.client.get(
393395
reverse("product-list"),
394396
data={"sideload": "categories,suppliers,partners"},
395397
format="json",
396398
)
397399

398-
expected_error_message = "Sideloadable prefetch values must be presented either as a list or a string"
399-
400-
raised_exception = cm.exception
401-
self.assertEqual(str(raised_exception), expected_error_message)
402-
403-
404400
class TestDrfSideloadingValidPrefetches(TestCase):
405401
"""Run tests while including mixin but not defining sideloading"""
406402

@@ -412,13 +408,15 @@ class ProductSideloadableSerializer(SideLoadableSerializer):
412408
products = ProductSerializer(many=True)
413409
categories = CategorySerializer(source="category", many=True)
414410
suppliers = SupplierSerializer(source="supplier", many=True)
411+
suppliers_ordered_by_name = SupplierSerializer(source="supplier", many=True)
415412
partners = PartnerSerializer(many=True)
416413

417414
class Meta:
418415
primary = "products"
419416
prefetches = {
420417
"categories": "category",
421418
"suppliers": ["supplier"],
419+
"suppliers_ordered_by_name": Prefetch("supplier", queryset=Supplier.objects.order_by("name")),
422420
"partners": None,
423421
}
424422

@@ -427,7 +425,7 @@ class Meta:
427425
def test_sideloading_with_prefetches(self):
428426
self.client.get(
429427
reverse("product-list"),
430-
data={"sideload": "categories,suppliers,partners"},
428+
data={"sideload": "categories,suppliers,suppliers_ordered_by_name,partners"},
431429
format="json",
432430
)
433431

0 commit comments

Comments
 (0)