Django Rest Framework – API Versioning

API versioning allows you to manage API behavior between different clients.


Versioning is required when there is a breaking change in the response data. Changing response format or response type (string data type to int data type) is considered as breaking change. Adding new response parameters is not considered as breaking change as this will not affect the existing API integrations.


At API’s end, versioning is determined by client requests. A client can pass version information either in the request URL or in the request headers. The way, a client passes version information is called “versioning scheme”. There are four common versioning scheme.

1. URI Path Versioning
Client passes version number in request url

2. Query parameter Versioning
Client passes version number in request url as a key-value pair.

3. Versioning using headers

Request Header “Accepts-version: 1.0”
Client passes version number in request header.

4. Versioning through content negotiation

Request Header “Accept: application/vnd.xm.device+json; version=1”
Client passes version number in request header.


Here we will see how we can implement URL path versioning in Django Rest Framework.

Add versioning Scheme in project’s file

'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning'

Hope, you have already Included your django app’s urls in your django project’s file. If not, you can do this by including your app’s urls files in project’s file.
urlpatterns = [
path('api/', include('api.urls')),

Project app’s

from django.urls import path, re_path
from django.conf.urls import url

url(r'^(?P<version>(v1))/categories/$', views.Categories.as_view()),
re_path(r'^(?P<version>(v1))/categories/(?P<pk>\d+)/$', views.CategoryDetails.as_view()),


In Project App’s, You can access requested version number using “request.version”.  Is it assumed that you have installed the request module in your django project.

print("request.version: ",request.version)

List page API

class Categories(APIView):

   List all Categories.

   def get(self, request, *args, **kwargs):
       #print("version:", request.version)
       queryset = Categories.objects.all()
       resultSet = CategoriesSerializer(queryset, many=True)

       return Response(


Category Details API

class CategoryDetails(APIView):

   Retrieve a category instance.

   def get_object(self, pk):
           return Categories.objects.get(pk=pk)
       except Categories.DoesNotExist:
           raise Http404

   def get(self, request, *args, **kwargs):
       pk = kwargs['pk']
       category = self.get_object(pk)
       serializer = CategoriesSerializer(category)

       return Response(


Note: in Official documentation, definitions get() is described as shown below:

 def get(self, request, pk, format=None):

This definition work when you are not using versioning. When you are using versioning, you need to modify the get() definition as there is an additional parameter <version> in the re_path which will not satisfy the get() definition. Modify the get() definition as shown in the above code:

def get(self, request, *args, **kwargs):

Also, in this case, you can get PK and version number in kwargs parameter.


Leave a Reply

Your email address will not be published. Required fields are marked *

Back to Top