Django Rest Framework is a very solid api framework, but it doesn’t provide out-of-box versioning mechanism, here is my attempt to implement version specific APIs.
The goal is to achieve something like
http://localhost:8000/api/(resource)/
http://localhost:8000/api/v1/(resource)/
plus allowing clients to specify the version in request header (X-Version), here is how we did it.
Structure in side the API app:
├── __init__.py
├── middlewares.py
├── urls.py
├── v1
│ ├── __init__.py
│ ├── account
│ │ ├── __init__.py
│ │ ├── serializers.py
│ │ └── views.py
│ └── urls.py
└── v2
├── __init__.py
├── account
│ ├── __init__.py
│ ├── serializers.py
│ └── views.py
└── urls.py
project urls.py:
url(r'^api/', include('project.api.urls', namespace='api')),
api app level urls.py:
from django.conf.urls import * urlpatterns = patterns('', url(r'', include('project.api.v2.urls', namespace='default')), url(r'^v1/', include('project.api.v1.urls', namespace='v1')), )
version level urls.py
from django.conf.urls import * from .account import views as account_views from rest_framework.routers import DefaultRouter router = DefaultRouter() router.register('account', account_views.AccountView) router.register('myaccount', account_views.MyAccountView) urlpatterns = router.urls
create a middleware to switch to the correct code by changing the path_info, please note there is a caveat that namespace (‘api’) defined in project level urls is not flexible and needs to be known in middleware:
from django.core.urlresolvers import resolve from django.core.urlresolvers import reverse class VersionSwitch(object): def process_request(self, request): r = resolve(request.path_info) version = request.META.get('HTTP_X_VERSION', False) if r.namespace.startswith('api:') and version: old_version = r.namespace.split(':')[-1] request.path_info = reverse('{}:{}'.format(r.namespace.replace(old_version, version), r.url_name), args=r.args, kwargs=r.kwargs)
Sample url:
curl -H "X-Version: v1" http://your.domain:8000/api/myaccount/
My original answer on stackoverflow.
Hello. I’m new to the DRF. I tried to write an example by your description and share it, but I get the error “NoReverseMatch at / app_drf/v1 /”.
Please see that was not written correctly.
https://github.com/van2048/DRF_versioning
You don’t have any API endpoints defined in the urls.py in v1 folder.
Do you have a repo with this example?
no sorry, I don’t know there anymore so don’t have the code.