DEV Community

Cover image for The Best Way to Implement API Versioning in Django REST Framework (Agile) 💎
Suliman Awad
Suliman Awad

Posted on

The Best Way to Implement API Versioning in Django REST Framework (Agile) 💎

API versioning is one of the most important topics in backend development. It ensures that live applications continue running smoothly even when changes are made to the APIs, preventing any downtime or disruptions.

In this article, we’ll explore how to implement API versioning in Django REST Framework in the best and simplest way.

API Versioning in the URL:

Even if your project is already live and running on production servers, this method ensures backward compatibility. It allows for the version to be optional in the URL, defaulting to version 1 if no version is specified.

To implement API versioning, we need to make three key changes to our project:

  1. Create a custom versioning class.
  2. Set the custom versioning class as the default in the project settings.
  3. Allow an optional version in the URL prefix for the entire project.

Creating the Versioning Class:

First, create the following file in your project: Project/common/rest_framework/api_versioning.py

from rest_framework import versioning

class CustomURLPathVersioning(versioning.URLPathVersioning):
    default_version = 1
    version_param = 'version'

VERSION = r'v(?P<version>\d+)/'
OPTIONAL_VERSION = r'(v(?P<version>\d+)/)?'
Enter fullscreen mode Exit fullscreen mode

Setting the Versioning Class as the Default:

Next, set the versioning class as the default in your settings.py file:

# Project/settings.py

REST_FRAMEWORK = {
    # Other REST framework settings...

    'DEFAULT_VERSIONING_CLASS': 'common.rest_framework.api_versioning.CustomURLPathVersioning',
}
Enter fullscreen mode Exit fullscreen mode

Accepting the Optional Version in the URL Prefix:

Now, modify your urls.py file to allow an optional version in the URL:

# Project/urls.py
from django.urls import path, re_path, include
from common.rest_framework.api_versioning import OPTIONAL_VERSION

app_patterns = [
    path('app1/', include('app1.urls')),
    path('app2/', include('app2.urls')),
]

urlpatterns = [
    # Other URL patterns...
    re_path(rf'^api/{OPTIONAL_VERSION}', include(app_patterns)),
]
Enter fullscreen mode Exit fullscreen mode

If your project is already using path in the URL definitions, you’ll need to replace it with re_path and add the {OPTIONAL_VERSION} prefix to all your API URLs.

Usage:

Now that versioning is in place, you can access the version in your views using the request.version property. You can then handle your versioning logic based on this property. A common and clear approach is to return a specific serializer for each version.

Example:

class TestAPIView(APIView):
    def get_serializer_class(self):
        if self.request.version == 2:
            return TestSerializerV2
        return TestSerializer
Enter fullscreen mode Exit fullscreen mode

In this example:

  • If the URL is called without a version (/api/endpoint or /api/v1/endpoint), the default version (1) will be used, returning the original serializer (TestSerializer).
  • If the URL includes version 2 (/api/v2/endpoint), the version will be considered 2, and the new serializer (TestSerializerV2) will be returned.

Conclusion:

With this setup, you can easily implement API versioning in Django REST Framework without disrupting existing functionality or causing issues for live applications. This method ensures flexibility, stability, and smooth transitions as you evolve your API.

Happy coding, and may your projects continue to run stably with proper API versioning! 😊

Top comments (0)