Example app with two approaches for versioning API with django rest framework
First approach implemented in alpha
django application.
With this approach api v1 and v2 shares model, but has it's own views and serializers.
Second approach implemented in beta
django application.
With this approach api v1 and v2 shares model and view, but has it's own serializers.
To share view for both versions SerializerClassMixin
is introduced.
It's possible to mix both approaches even in same djanogo application.
Each application exposes router
which is drf SimpleRouter
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register(r'app', AppViewSet)
Main urls.py instantiate DefaultRouter and extend it with application routers
from rest_framework.routers import DefaultRouter
from alpha.api_v1.urls import router as alpha_v1_router
from alpha.api_v2.urls import router as alpha_v2_router
from beta.api.urls imprt router as beta_router
v1_router = DefaultRouter()
v1_router.registry.extend(alpha_v1_router.registry)
v1_router.registry.extend(beta_router)
v2_router = DefaultRouter()
v2_router.registry.extend(alpha_v2_router.registry)
v2_router.registry.extend(beta_router.registry)
urlpatterns = [
path('api/v1/', include((v1_router.urls, 'api'), namespace='v1')),
path('api/v2/', include((v2_router.urls, 'api'), namespace='v2')),
]
Application structure
├── api_v1
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── api_v2
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── apps.py
└── models.py
The reason for copy and paste views, serializers and urls is to be able to change anything in specific version and do not affect another one.
Application structure
├── api
│ ├── v1
│ │ └── serializers.py
│ ├── v2
│ │ └── serializers.py
│ ├── urls.py
│ └── views.py
├── apps.py
├── mixins.py
└── models.py
In this case SerializerClassMixin
is introduced, so we can define view this way:
version_map = {
'v1': BetaSerializer_v1,
'v2': BetaSerializer_v2,
}
class BetaViewSet(SerializerClassMixin, viewsets.ModelViewSet):
version_map = version_map
queryset = Beta.objects.all()
Key for the version_map
should be same we have in main urls.py
namespace for specific path.