Skip to content

Commit 9e17bcb

Browse files
committed
add test case for "get_sideloadable_serializer_class"
1 parent 3a0fc6e commit 9e17bcb

File tree

3 files changed

+104
-33
lines changed

3 files changed

+104
-33
lines changed

tests/serializers.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,26 @@ class Meta:
6464
"backup_supplier": ["backup_supplier"],
6565
},
6666
}
67+
68+
69+
class NewProductSideloadableSerializer(SideLoadableSerializer):
70+
products = ProductSerializer(many=True)
71+
new_categories = CategorySerializer(source="category", many=True)
72+
new_main_suppliers = SupplierSerializer(source="supplier", many=True)
73+
new_backup_suppliers = SupplierSerializer(source="backup_supplier", many=True)
74+
new_partners = PartnerSerializer(source="partner", many=True)
75+
combined_suppliers = SupplierSerializer(many=True)
76+
77+
class Meta:
78+
primary = "products"
79+
prefetches = {
80+
"new_categories": "category",
81+
"new_main_suppliers": "supplier",
82+
"new_backup_suppliers": "backup_supplier",
83+
"new_partners": "partners",
84+
# These can be defined to always load them, else they will be copied over form all sources or selected sources only.
85+
"combined_suppliers": {
86+
"suppliers": ["supplier"],
87+
"backup_supplier": ["backup_supplier"],
88+
},
89+
}

tests/test_products_api.py

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88

99
from drf_sideloading.serializers import SideLoadableSerializer
1010
from tests.models import Category, Supplier, Product, Partner
11-
from tests.serializers import ProductSerializer, CategorySerializer, SupplierSerializer, PartnerSerializer
11+
from tests.serializers import (
12+
ProductSerializer,
13+
CategorySerializer,
14+
SupplierSerializer,
15+
PartnerSerializer,
16+
)
1217
from tests.viewsets import ProductViewSet
1318

1419

@@ -58,7 +63,7 @@ class ProductSideloadTestCase(BaseTestCase):
5863
def setUpClass(cls):
5964
super(ProductSideloadTestCase, cls).setUpClass()
6065

61-
class ProductSideloadableSerializer(SideLoadableSerializer):
66+
class TempProductSideloadableSerializer(SideLoadableSerializer):
6267
products = ProductSerializer(many=True)
6368
categories = CategorySerializer(source="category", many=True)
6469
suppliers = SupplierSerializer(source="supplier", many=True)
@@ -72,7 +77,7 @@ class Meta:
7277
"partners": "partners",
7378
}
7479

75-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
80+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
7681

7782
def test_list(self):
7883
response = self.client.get(path=reverse("product-list"), **self.DEFAULT_HEADERS)
@@ -184,7 +189,7 @@ class ProductMultiSourceSideloadTestCase(BaseTestCase):
184189
def setUpClass(cls):
185190
super(ProductMultiSourceSideloadTestCase, cls).setUpClass()
186191

187-
class ProductSideloadableSerializer(SideLoadableSerializer):
192+
class TempProductSideloadableSerializer(SideLoadableSerializer):
188193
products = ProductSerializer(many=True)
189194
categories = CategorySerializer(source="category", many=True)
190195
main_suppliers = SupplierSerializer(source="supplier", many=True)
@@ -206,7 +211,7 @@ class Meta:
206211
},
207212
}
208213

209-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
214+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
210215

211216
def setUp(self):
212217
super().setUp()
@@ -343,13 +348,13 @@ class TestDrfSideloadingNoMetaClassDefined(BaseTestCase):
343348
def setUpClass(cls):
344349
super(TestDrfSideloadingNoMetaClassDefined, cls).setUpClass()
345350

346-
class ProductSideloadableSerializer(SideLoadableSerializer):
351+
class TempProductSideloadableSerializer(SideLoadableSerializer):
347352
products = ProductSerializer(many=True)
348353
categories = CategorySerializer(many=True)
349354
suppliers = SupplierSerializer(many=True)
350355
partners = PartnerSerializer(many=True)
351356

352-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
357+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
353358

354359
def test_correct_exception_raised(self):
355360
expected_error_message = "Sideloadable serializer must have a Meta class defined with the 'primary' field name!"
@@ -368,7 +373,7 @@ class TestDrfSideloadingNoPrimaryDefined(BaseTestCase):
368373
def setUpClass(cls):
369374
super(TestDrfSideloadingNoPrimaryDefined, cls).setUpClass()
370375

371-
class ProductSideloadableSerializer(SideLoadableSerializer):
376+
class TempProductSideloadableSerializer(SideLoadableSerializer):
372377
products = ProductSerializer(many=True)
373378
categories = CategorySerializer(many=True)
374379
suppliers = SupplierSerializer(many=True)
@@ -377,7 +382,7 @@ class ProductSideloadableSerializer(SideLoadableSerializer):
377382
class Meta:
378383
pass
379384

380-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
385+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
381386

382387
def test_correct_exception_raised(self):
383388
expected_error_message = "Sideloadable serializer must have a Meta class defined with the 'primary' field name!"
@@ -396,7 +401,7 @@ class TestDrfSideloadingRelationsNotListSerializers(BaseTestCase):
396401
def setUpClass(cls):
397402
super(TestDrfSideloadingRelationsNotListSerializers, cls).setUpClass()
398403

399-
class ProductSideloadableSerializer(SideLoadableSerializer):
404+
class TempProductSideloadableSerializer(SideLoadableSerializer):
400405
products = ProductSerializer(many=True)
401406
categories = CategorySerializer()
402407
suppliers = SupplierSerializer()
@@ -405,7 +410,7 @@ class ProductSideloadableSerializer(SideLoadableSerializer):
405410
class Meta:
406411
primary = "products"
407412

408-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
413+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
409414

410415
def test_correct_exception_raised(self):
411416
expected_error_message = "SideLoadable field 'categories' must be set as many=True"
@@ -422,7 +427,7 @@ class TestDrfSideloadingInvalidPrimary(BaseTestCase):
422427
def setUpClass(cls):
423428
super(TestDrfSideloadingInvalidPrimary, cls).setUpClass()
424429

425-
class ProductSideloadableSerializer(SideLoadableSerializer):
430+
class TempProductSideloadableSerializer(SideLoadableSerializer):
426431
products = ProductSerializer(many=True)
427432
categories = CategorySerializer(many=True)
428433
suppliers = SupplierSerializer(many=True)
@@ -431,7 +436,7 @@ class ProductSideloadableSerializer(SideLoadableSerializer):
431436
class Meta:
432437
primary = "other"
433438

434-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
439+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
435440

436441
def test_correct_exception_raised(self):
437442
expected_error_message = "Sideloadable serializer Meta.primary must point to a field in the serializer!"
@@ -450,7 +455,7 @@ class TestDrfSideloadingInvalidPrefetchesType(BaseTestCase):
450455
def setUpClass(cls):
451456
super(TestDrfSideloadingInvalidPrefetchesType, cls).setUpClass()
452457

453-
class ProductSideloadableSerializer(SideLoadableSerializer):
458+
class TempProductSideloadableSerializer(SideLoadableSerializer):
454459
products = ProductSerializer(many=True)
455460
categories = CategorySerializer(many=True)
456461
suppliers = SupplierSerializer(many=True)
@@ -464,7 +469,7 @@ class Meta:
464469
("partners", "partners"),
465470
)
466471

467-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
472+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
468473

469474
def test_correct_exception_raised(self):
470475
expected_error_message = "Sideloadable serializer Meta attribute 'prefetches' must be a dict."
@@ -483,7 +488,7 @@ class TestDrfSideloadingInvalidPrefetchesValuesType(BaseTestCase):
483488
def setUpClass(cls):
484489
super(TestDrfSideloadingInvalidPrefetchesValuesType, cls).setUpClass()
485490

486-
class ProductSideloadableSerializer(SideLoadableSerializer):
491+
class TempProductSideloadableSerializer(SideLoadableSerializer):
487492
products = ProductSerializer(many=True)
488493
categories = CategorySerializer(many=True)
489494
suppliers = SupplierSerializer(many=True)
@@ -497,7 +502,7 @@ class Meta:
497502
"partners": 123,
498503
}
499504

500-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
505+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
501506

502507
def test_correct_exception_raised(self):
503508
expected_error_message = "prefetch with type '<class 'int'>' is not implemented"
@@ -519,7 +524,7 @@ class TestDrfSideloadingValidPrefetches(BaseTestCase):
519524
def setUpClass(cls):
520525
super(TestDrfSideloadingValidPrefetches, cls).setUpClass()
521526

522-
class ProductSideloadableSerializer(SideLoadableSerializer):
527+
class TempProductSideloadableSerializer(SideLoadableSerializer):
523528
products = ProductSerializer(many=True)
524529
categories = CategorySerializer(source="category", many=True)
525530
suppliers = SupplierSerializer(source="supplier", many=True)
@@ -534,6 +539,7 @@ class Meta:
534539
prefetches = {
535540
"categories": "category",
536541
"suppliers": ["supplier"],
542+
"partners": ["partners"],
537543
"filtered_suppliers": Prefetch(
538544
lookup="supplier",
539545
queryset=Supplier.objects.filter(name__in=["Supplier2", "Supplier4"]),
@@ -568,7 +574,7 @@ class Meta:
568574
},
569575
}
570576

571-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
577+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
572578

573579
def test_sideloading_with_dual_usage_prefetches(self):
574580
response_2 = self.client.get(
@@ -612,7 +618,6 @@ def test_sideloading_with_dual_usage_prefetches(self):
612618
# filtered_partner_names = {partner["name"] for partner in response_1.json()["filtered_partners"]}
613619
# self.assertSetEqual({"Partner2", "Partner4"}, filtered_partner_names)
614620
#
615-
#
616621
# # fixme: for some reason, the filtered_suppliers is not sideloaded altho Prefetch present in queryset arguments
617622
# def test_sideloading_with_filtered_prefetch(self):
618623
# response_1 = self.client.get(
@@ -688,7 +693,7 @@ class TestDrfSideloadingInvalidPrefetchSource(BaseTestCase):
688693
def setUpClass(cls):
689694
super(TestDrfSideloadingInvalidPrefetchSource, cls).setUpClass()
690695

691-
class ProductSideloadableSerializer(SideLoadableSerializer):
696+
class TempProductSideloadableSerializer(SideLoadableSerializer):
692697
products = ProductSerializer(many=True)
693698
categories = CategorySerializer(source="category", many=True)
694699
suppliers = SupplierSerializer(source="supplier", many=True)
@@ -737,7 +742,7 @@ class Meta:
737742
},
738743
}
739744

740-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
745+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
741746

742747
def test_sideloading_combined_suppliers_with_mismatching_to_attr_and_source(self):
743748
msg = (
@@ -762,7 +767,7 @@ class TestDrfSideloadingValidPrefetchObjectsImplicit(BaseTestCase):
762767
def setUpClass(cls):
763768
super(TestDrfSideloadingValidPrefetchObjectsImplicit, cls).setUpClass()
764769

765-
class ProductSideloadableSerializer(SideLoadableSerializer):
770+
class TempProductSideloadableSerializer(SideLoadableSerializer):
766771
products = ProductSerializer(many=True)
767772
categories = CategorySerializer(source="category", many=True)
768773
suppliers = SupplierSerializer(source="supplier", many=True)
@@ -782,7 +787,7 @@ class Meta:
782787
),
783788
}
784789

785-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
790+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
786791

787792
# TODO: fix test as we get an error: "Two different prefetches for the same attribute"
788793
# def test_sideloading_with_prefetch_object_without_to_attr(self):
@@ -804,7 +809,7 @@ class TestDrfSideloadingPrefetchObjectsMatchingLookup(BaseTestCase):
804809
def setUpClass(cls):
805810
super(TestDrfSideloadingPrefetchObjectsMatchingLookup, cls).setUpClass()
806811

807-
class ProductSideloadableSerializer(SideLoadableSerializer):
812+
class TempProductSideloadableSerializer(SideLoadableSerializer):
808813
products = ProductSerializer(many=True)
809814
categories = CategorySerializer(source="category", many=True)
810815
suppliers = SupplierSerializer(source="supplier", many=True)
@@ -822,7 +827,7 @@ class Meta:
822827
),
823828
}
824829

825-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
830+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
826831

827832
def test_sideloading_with_prefetch_object_without_to_attr_but_lookup_matching_field(self):
828833
response_1 = self.client.get(
@@ -852,7 +857,7 @@ class TestDrfSideloadingInvalidPrefetchObject(BaseTestCase):
852857
def setUpClass(cls):
853858
super(TestDrfSideloadingInvalidPrefetchObject, cls).setUpClass()
854859

855-
class ProductSideloadableSerializer(SideLoadableSerializer):
860+
class TempProductSideloadableSerializer(SideLoadableSerializer):
856861
products = ProductSerializer(many=True)
857862
categories = CategorySerializer(source="category", many=True)
858863
suppliers = SupplierSerializer(source="supplier", many=True)
@@ -878,7 +883,7 @@ class Meta:
878883
),
879884
}
880885

881-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
886+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
882887

883888
# # TODO: fix this for cases where field source is present but Prefetch.to_attr mismatches
884889
# def test_sideloading_with_prefetches(self):
@@ -908,7 +913,7 @@ def has_permission(self, request, view):
908913
def has_object_permission(self, request, view, obj):
909914
raise ValueError("This must not be called, when sideloadading is used!")
910915

911-
class ProductSideloadableSerializer(SideLoadableSerializer):
916+
class TempProductSideloadableSerializer(SideLoadableSerializer):
912917
products = ProductSerializer(many=True)
913918
categories = CategorySerializer(source="category", many=True)
914919
suppliers = SupplierSerializer(source="supplier", many=True)
@@ -924,7 +929,7 @@ class Meta:
924929

925930
ProductViewSet.renderer_classes = (BrowsableAPIRenderer, JSONRenderer)
926931
ProductViewSet.permission_classes = (ProductPermission,)
927-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
932+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
928933

929934
@classmethod
930935
def tearDownClass(cls):
@@ -992,7 +997,7 @@ class Meta:
992997
model = Category
993998
fields = ["old_name"]
994999

995-
class ProductSideloadableSerializer(SideLoadableSerializer):
1000+
class TempProductSideloadableSerializer(SideLoadableSerializer):
9961001
products = ProductSerializer(many=True)
9971002
categories = CategorySerializer(source="category", many=True)
9981003
old_categories = OldCategorySerializer(source="category", many=True)
@@ -1003,7 +1008,7 @@ class Meta:
10031008
primary = "products"
10041009
prefetches = {"category": "category", "old_categories": "category"}
10051010

1006-
ProductViewSet.sideloading_serializer_class = ProductSideloadableSerializer
1011+
ProductViewSet.sideloading_serializer_class = TempProductSideloadableSerializer
10071012

10081013
def test_list_sideload_categories(self):
10091014
response = self.client.get(
@@ -1031,3 +1036,38 @@ def test_list_sideload_new_categories_and_old_categories(self):
10311036
self.assertIsInstance(response.json(), dict)
10321037
self.assertListEqual(["products", "category"], list(response.data.serializer.instance.keys()))
10331038
self.assertListEqual(["products", "categories", "old_categories"], list(response.json().keys()))
1039+
1040+
1041+
class VersionesSideloadableSerializerTestCase(BaseTestCase):
1042+
def test_list_sideload_categories(self):
1043+
# old as example
1044+
response = self.client.get(
1045+
path=reverse("product-list"),
1046+
data={"sideload": "categories"},
1047+
# headers:
1048+
HTTP_ACCEPT="application/json; version=1.0",
1049+
)
1050+
self.assertEqual(response.status_code, status.HTTP_200_OK)
1051+
self.assertIsInstance(response.json(), dict)
1052+
self.assertListEqual(["products", "categories"], list(response.json().keys()))
1053+
1054+
# new version can't sideload this value
1055+
response = self.client.get(
1056+
path=reverse("product-list"),
1057+
data={"sideload": "categories"},
1058+
# headers:
1059+
HTTP_ACCEPT="application/json; version=2.0.0",
1060+
)
1061+
self.assertEqual(response.status_code, status.HTTP_200_OK)
1062+
self.assertIsInstance(response.json(), list)
1063+
1064+
# new version called correctly
1065+
response = self.client.get(
1066+
path=reverse("product-list"),
1067+
data={"sideload": "new_categories"},
1068+
# headers:
1069+
HTTP_ACCEPT="application/json; version=2.0.0",
1070+
)
1071+
self.assertEqual(response.status_code, status.HTTP_200_OK)
1072+
self.assertIsInstance(response.json(), dict)
1073+
self.assertListEqual(["products", "new_categories"], list(response.json().keys()))

tests/viewsets.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from rest_framework import viewsets, filters
1+
from rest_framework import viewsets, filters, versioning
22

33
from drf_sideloading.mixins import SideloadableRelationsMixin
44
from tests.mixins import OtherMixin
@@ -10,6 +10,7 @@
1010
PartnerSerializer,
1111
ProductSideloadableSerializer,
1212
CategorySideloadableSerializer,
13+
NewProductSideloadableSerializer,
1314
)
1415

1516

@@ -21,6 +22,7 @@ class ProductViewSet(SideloadableRelationsMixin, OtherMixin, viewsets.ModelViewS
2122
queryset = Product.objects.all()
2223
serializer_class = ProductSerializer
2324
sideloading_serializer_class = ProductSideloadableSerializer
25+
versioning_class = versioning.AcceptHeaderVersioning
2426
filter_backends = [
2527
filters.SearchFilter,
2628
# django_filters.rest_framework.DjangoFilterBackend,
@@ -32,6 +34,12 @@ def get_serializer_class(self):
3234
# if no super is called sideloading should still work
3335
return self.serializer_class
3436

37+
def get_sideloading_serializer_class(self):
38+
# if no super is called sideloading should still work
39+
if self.request.version == "2.0.0":
40+
return NewProductSideloadableSerializer
41+
return self.sideloading_serializer_class
42+
3543

3644
class CategoryViewSet(SideloadableRelationsMixin, viewsets.ModelViewSet):
3745
queryset = Category.objects.all()

0 commit comments

Comments
 (0)