Django URLPathVersioning: Clean, Flexible API Versioning in Your URLs
Last updated 4 months ago | 370 views 75 5

Introduction: Why API Versioning Matters
In any real-world API, changes are inevitable—you’ll need to introduce improvements, fix bugs, or modify existing endpoints. But making changes to a live API can break integrations for existing users. That’s why API versioning is essential.
URLPathVersioning is one of the most straightforward and readable ways to handle versioning in Django REST Framework (DRF). It places the version directly in the URL, making version management intuitive and visible.
✅ Example:
/api/v1/posts/
vs/api/v2/posts/
This approach helps developers:
-
Maintain backward compatibility
-
Avoid breaking existing clients
-
Transition to newer versions safely
⚙️ Setting Up URLPathVersioning in Django REST Framework
✅ Step 1: Configure DRF Settings
In your settings.py
, define the versioning scheme:
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
'DEFAULT_VERSION': 'v1',
'ALLOWED_VERSIONS': ['v1', 'v2'],
'VERSION_PARAM': 'version',
}
Here’s what each setting does:
-
DEFAULT_VERSIONING_CLASS
: Specifies that versioning will be done via URL paths. -
DEFAULT_VERSION
: Sets a fallback version. -
ALLOWED_VERSIONS
: Lists the supported versions. -
VERSION_PARAM
: Name of the version parameter (used internally, not visible in the URL).
✅ Step 2: Define URL Patterns with Versioning
In urls.py
, include the version directly in the path:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PostViewSet
router = DefaultRouter()
router.register(r'posts', PostViewSet, basename='posts')
urlpatterns = [
path('api/<str:version>/', include(router.urls)),
]
This tells Django to expect a version
like v1
or v2
in the URL.
✅ Step 3: Access Version in Your Views (If Needed)
You can access the version inside views or viewsets via:
class PostViewSet(viewsets.ViewSet):
def list(self, request):
version = request.version # v1 or v2
return Response({'version': version, 'message': 'List of posts'})
Complete Example
Let’s create a minimal DRF app with versioned API.
views.py
from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
class PostViewSet(ViewSet):
def list(self, request):
return Response({
"version": request.version,
"posts": ["Post A", "Post B"]
})
def retrieve(self, request, pk=None):
return Response({
"version": request.version,
"post": f"Post {pk}"
})
urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PostViewSet
router = DefaultRouter()
router.register(r'posts', PostViewSet, basename='posts')
urlpatterns = [
path('api/<str:version>/', include(router.urls)),
]
Example Requests
-
GET /api/v1/posts/
→ Returns list with version = v1 -
GET /api/v2/posts/
→ Also works (ifv2
is allowed in settings)
⚠️ Tips & Common Pitfalls
✅ Best Practices
-
Document supported versions in your API docs (Swagger/ReDoc).
-
Keep older versions available for backward compatibility.
-
Use clear naming like
v1
,v2
, etc., not1.0
,2.0
.
❌ Common Pitfalls
Problem | Solution |
---|---|
Missing version in URL | Ensure <str:version>/ is in urls.py |
Version not passed correctly | Use request.version , not query param |
Unsupported version errors | Add version to ALLOWED_VERSIONS in settings |
Breaking changes without new version | Always increment version on breaking changes |
Comparison: URLPathVersioning vs Other Schemes
Versioning Scheme | Example URI | Use Case |
---|---|---|
URLPathVersioning | /api/v1/posts/ |
Clear and visible versioning |
NamespaceVersioning | /v1/posts/ (namespaced apps) |
Useful for app-based separation |
AcceptHeaderVersioning | Use Accept header |
Cleaner URLs, but harder to debug |
QueryParameterVersioning | /posts/?version=v1 |
Easy to test, less RESTful |
Conclusion: Version Your APIs Like a Pro
Versioning your APIs is non-negotiable in any production system. URLPathVersioning is simple, intuitive, and REST-friendly. It helps your teams deploy confidently without worrying about breaking clients.
✅ Key Takeaways
-
Use
URLPathVersioning
for visible and explicit versioning. -
Keep old versions around as needed.
-
Always test new versions before deprecating older ones.
-
Combine versioning with docs (like Swagger/ReDoc) for developer happiness.