Skip to content

Commit

Permalink
Merge pull request #28 from stefanofusai/27-add-support-for-versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanofusai authored Oct 16, 2024
2 parents bbaec4b + 7e70d02 commit 5fe1270
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 6 deletions.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ from drf_multi_serializers import MultiSerializerMixin

...

class MyAPIView(MultiSerializerMixin, ListCreateAPIView):
class MyListCreateAPIView(MultiSerializerMixin, ListCreateAPIView):
...
serializer_classes = {
"create": MyCreateSerializer,
Expand All @@ -40,6 +40,36 @@ class MyViewSet(MultiSerializerMixin, ModelViewSet):
...
```

drf-multi-serializers also supports Django Rest Framework's versioning system!

```python
from rest_framework.generics import ListCreateAPIView
from rest_framework.viewsets import ModelViewSet
from drf_multi_serializers import MultiSerializerMixin

...

class MyAPIView(MultiSerializerMixin, APIView):
...
serializer_classes = {
"v1": MyV1Serializer,
"v2": MyV2Serializer,
}
...

class MyViewSet(MultiSerializerMixin, ModelViewSet):
...
serializer_classes = {
"create": {"v1": MyV1CreateSerializer, "v2": MyV2CreateSerializer},
"list": MyListSerializer,
"metadata": MyMetadataSerializer, # create ViewSets require either serializer_class or metadata serializer for OPTION requests
"partial_update": MyUpdateSerializer,
"retrieve": MyRetrieveSerializer,
"update": MyUpdateSerializer,
}
...
```

## Contributing

Contributions are welcome! To get started, please refer to our [contribution guidelines](https://github.com/stefanofusai/drf-multi-serializers/blob/main/CONTRIBUTING.md).
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "drf-multi-serializers"
version = "1.1.1"
version = "1.2.0"
authors = [{ "name" = "Stefano Fusai", "email" = "[email protected]" }]
description = "Handle multiple serializers for the same view in Django Rest Framework."
readme = "README.md"
Expand Down
5 changes: 5 additions & 0 deletions src/drf_multi_serializers/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class ActionVersionSetError(Exception):
"""Raised when serializer_classes matches against both action and version."""

def __init__(self) -> None: # noqa: D107
super().__init__("action and version can't be set at the same time")
29 changes: 25 additions & 4 deletions src/drf_multi_serializers/mixins.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
from rest_framework.serializers import Serializer

from .exceptions import ActionVersionSetError


class MultiSerializerMixin:
"""A mixin that allows you to define different serializers for different ViewSet actions."""
"""A mixin that allows you to define different serializers for different view actions/methods/versions."""

serializer_classes: dict[str, type[Serializer]]
serializer_classes: dict[str, type[Serializer] | dict[str, type[Serializer]]]

def get_serializer_class(self) -> type[Serializer]: # noqa: D102
if self.action in self.serializer_classes:
return self.serializer_classes[self.action]
action = getattr(self, "action", None)
version = self.request.version

if action in self.serializer_classes and version in self.serializer_classes:
raise ActionVersionSetError

if action is not None and action in self.serializer_classes:
action_serializer_or_versioned_serializers = self.serializer_classes[action]

if (
isinstance(action_serializer_or_versioned_serializers, dict)
and version is not None
and version in action_serializer_or_versioned_serializers
):
return action_serializer_or_versioned_serializers[version]

if issubclass(action_serializer_or_versioned_serializers, Serializer):
return action_serializer_or_versioned_serializers

if version is not None and version in self.serializer_classes:
return self.serializer_classes[version]

return super().get_serializer_class()

0 comments on commit 5fe1270

Please sign in to comment.