Skip to content

Commit 5fe1270

Browse files
authored
Merge pull request #28 from stefanofusai/27-add-support-for-versioning
2 parents bbaec4b + 7e70d02 commit 5fe1270

File tree

4 files changed

+62
-6
lines changed

4 files changed

+62
-6
lines changed

README.md

+31-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ from drf_multi_serializers import MultiSerializerMixin
1919

2020
...
2121

22-
class MyAPIView(MultiSerializerMixin, ListCreateAPIView):
22+
class MyListCreateAPIView(MultiSerializerMixin, ListCreateAPIView):
2323
...
2424
serializer_classes = {
2525
"create": MyCreateSerializer,
@@ -40,6 +40,36 @@ class MyViewSet(MultiSerializerMixin, ModelViewSet):
4040
...
4141
```
4242

43+
drf-multi-serializers also supports Django Rest Framework's versioning system!
44+
45+
```python
46+
from rest_framework.generics import ListCreateAPIView
47+
from rest_framework.viewsets import ModelViewSet
48+
from drf_multi_serializers import MultiSerializerMixin
49+
50+
...
51+
52+
class MyAPIView(MultiSerializerMixin, APIView):
53+
...
54+
serializer_classes = {
55+
"v1": MyV1Serializer,
56+
"v2": MyV2Serializer,
57+
}
58+
...
59+
60+
class MyViewSet(MultiSerializerMixin, ModelViewSet):
61+
...
62+
serializer_classes = {
63+
"create": {"v1": MyV1CreateSerializer, "v2": MyV2CreateSerializer},
64+
"list": MyListSerializer,
65+
"metadata": MyMetadataSerializer, # create ViewSets require either serializer_class or metadata serializer for OPTION requests
66+
"partial_update": MyUpdateSerializer,
67+
"retrieve": MyRetrieveSerializer,
68+
"update": MyUpdateSerializer,
69+
}
70+
...
71+
```
72+
4373
## Contributing
4474

4575
Contributions are welcome! To get started, please refer to our [contribution guidelines](https://github.com/stefanofusai/drf-multi-serializers/blob/main/CONTRIBUTING.md).

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "drf-multi-serializers"
7-
version = "1.1.1"
7+
version = "1.2.0"
88
authors = [{ "name" = "Stefano Fusai", "email" = "[email protected]" }]
99
description = "Handle multiple serializers for the same view in Django Rest Framework."
1010
readme = "README.md"
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class ActionVersionSetError(Exception):
2+
"""Raised when serializer_classes matches against both action and version."""
3+
4+
def __init__(self) -> None: # noqa: D107
5+
super().__init__("action and version can't be set at the same time")

src/drf_multi_serializers/mixins.py

+25-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,34 @@
11
from rest_framework.serializers import Serializer
22

3+
from .exceptions import ActionVersionSetError
4+
35

46
class MultiSerializerMixin:
5-
"""A mixin that allows you to define different serializers for different ViewSet actions."""
7+
"""A mixin that allows you to define different serializers for different view actions/methods/versions."""
68

7-
serializer_classes: dict[str, type[Serializer]]
9+
serializer_classes: dict[str, type[Serializer] | dict[str, type[Serializer]]]
810

911
def get_serializer_class(self) -> type[Serializer]: # noqa: D102
10-
if self.action in self.serializer_classes:
11-
return self.serializer_classes[self.action]
12+
action = getattr(self, "action", None)
13+
version = self.request.version
14+
15+
if action in self.serializer_classes and version in self.serializer_classes:
16+
raise ActionVersionSetError
17+
18+
if action is not None and action in self.serializer_classes:
19+
action_serializer_or_versioned_serializers = self.serializer_classes[action]
20+
21+
if (
22+
isinstance(action_serializer_or_versioned_serializers, dict)
23+
and version is not None
24+
and version in action_serializer_or_versioned_serializers
25+
):
26+
return action_serializer_or_versioned_serializers[version]
27+
28+
if issubclass(action_serializer_or_versioned_serializers, Serializer):
29+
return action_serializer_or_versioned_serializers
30+
31+
if version is not None and version in self.serializer_classes:
32+
return self.serializer_classes[version]
1233

1334
return super().get_serializer_class()

0 commit comments

Comments
 (0)