Подтвердить что ты не робот

Django-rest-framework: api versioning

поэтому поиск по всему миру кажется, что общий консенсус в том, что включение номеров версий в URI REST - это плохая практика и плохая идея.

даже на SO есть сильные сторонники, поддерживающие это.
например Рекомендации по управлению версиями API?

Мой вопрос в том, как выполнить предлагаемое решение использования согласования заголовка/содержимого accept в django-rest-framework для выполнения этого.

Это похоже на согласование контента в рамках,
http://django-rest-framework.org/api-guide/content-negotiation/ уже настроен на автоматическое возвращение целевых значений на основе принятых типов MIME. Если я начну использовать заголовок Accept для пользовательских типов, я потеряю это преимущество фреймворка.

Есть ли лучший способ сделать это в рамках?

4b9b3361

Ответ 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/