Django-rest-framework: api versioning
поэтому поиск по всему миру кажется, что общий консенсус в том, что включение номеров версий в URI REST - это плохая практика и плохая идея.
даже на SO есть сильные сторонники, поддерживающие это.
например Рекомендации по управлению версиями API?
Мой вопрос в том, как выполнить предлагаемое решение использования согласования заголовка/содержимого accept в django-rest-framework для выполнения этого.
Это похоже на согласование контента в рамках,
http://django-rest-framework.org/api-guide/content-negotiation/
уже настроен на автоматическое возвращение целевых значений на основе принятых типов MIME. Если я начну использовать заголовок Accept для пользовательских типов, я потеряю это преимущество фреймворка.
Есть ли лучший способ сделать это в рамках?
Ответы
Ответ 1
Один из способов сделать это - установить версию, указанную как часть типа носителя.
Это то, что GitHub в настоящее время делает для своего API.
Вы также можете включить параметры типа мультимедиа в заголовках accept, например Accept: application/json; version=beta
, который будет успешно соответствовать JSONRenderer
. Затем вы можете закодировать свое мнение, чтобы вести себя по-разному в зависимости от принятого типа носителя, см. здесь.
В API существует множество разных шаблонов для управления версиями, и я бы не сказал, что есть какой-либо большой консенсус вокруг правильного подхода, но это была бы разумная возможность.
Обновить январь 2015. Лучшая поддержка версий будет поступать в версии 3.1.0. См. [Этот запрос на растяжение]
Обновить март 2015: теперь доступны документы для API управления версиями .
(https://github.com/tomchristie/django-rest-framework/pull/2285) для более подробной информации.
Ответ 2
UPDATE:
versioning теперь правильно поддерживается.
Есть несколько ответов из вашей ссылки:
Мы нашли практичным и полезным разместить версию в URL-адресе. Это позволяет легко понять, что вы используете с первого взгляда. Мы выполняем псевдоним /foo to/foo/(последние версии) для удобства использования, более короткие/чистые URL-адреса, и т.д., как предполагает принятый ответ. Сохранение обратной совместимости навсегда часто является дорогостоящим и/или очень сложным. Мы предпочитаем давать предварительное уведомление о устаревание, перенаправления, как предлагается здесь, документы и другие механизмы.
Итак, мы использовали этот подход, а также позволяем клиентам указывать версию в заголовке запроса (X-Version), вот как мы это сделали:
Структура со стороны приложения API:
.
├── __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 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')),
)
уровень версии 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
создайте промежуточное программное обеспечение, чтобы переключиться на правильный код, изменив path_info, обратите внимание, что существует предостережение о том, что пространство имен ('api'), определенное в URL-адресах уровня проекта, не является гибким и должно быть известно в промежуточном программном обеспечении:
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)
Пример URL:
curl -H "X-Version: v1" http://your.domain:8000/api/myaccount/