web-dev-qa-db-ja.com

django-rest-framework:APIバージョン管理

そのため、グーグルで説明すると、REST URIにバージョン番号を埋め込むことは悪い習慣であり、悪い考えです。

SOでも、これを支持する強力な支持者がいます。
例えば。 APIバージョン管理のベストプラクティス?

私の質問は、Django-rest-frameworkでAcceptヘッダー/コンテンツネゴシエーションを使用して提案されたソリューションを実現する方法についてです。

フレームワークでのコンテンツ交渉のように見えますが、
http://Django-rest-framework.org/api-guide/content-negotiation/ は、受け入れられたMIMEタイプに基づいて意図した値を自動的に返すようにすでに設定されています。カスタムタイプにAcceptヘッダーを使い始めると、フレームワークのこの利点が失われます。

フレームワークでこれを達成するためのより良い方法はありますか?

32
w--

これを行う1つの方法は、バージョンをメディアタイプの一部として指定することです。

これがGitHub 現在APIのために行っている です。

また、JSONRendererと正常に一致するAccept: application/json; version=betaなどのメディアタイプパラメータをAcceptヘッダーに含めることもできます。次に、受け入れたメディアタイプに応じて異なる動作をするようにビューをコーディングできます。 ここ を参照してください。

APIのバージョン管理にはさまざまなパターンがたくさんありますが、適切なアプローチについてはまだ十分なコンセンサスがあるとは言えませんが、それは1つの合理的な可能性です。


2015年1月更新:3.1.0リリースで、より優れたバージョン管理サポートが導入される予定です。 [このプルリクエスト]を参照してください

2015年3月更新:バージョン管理APIのドキュメント 利用可能になりました

https://github.com/tomchristie/Django-rest-framework/pull/2285 )詳細については。

30
Tom Christie

UPDATE:

versioning が適切にサポートされるようになりました。


あなたのリンクからいくつかの答えがあります:

URLにバージョンを含めることは実用的で便利であることがわかりました。使用しているものを一目で簡単に確認できます。受け入れられた回答が示唆するように、使いやすさ、より短い/よりクリーンなURLなどのために、/ foo /(最新バージョン)に/ fooをエイリアスします。下位互換性を永久に維持することは、多くの場合、コストがかかり、非常に困難です。廃止予定の事前通知、ここで提案されているようなリダイレクト、ドキュメント、その他のメカニズムを提供することをお勧めします。

そこで、このアプローチを採用し、さらにクライアントがリクエストヘッダー(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

プロジェクトurls.py:

url(r'^api/', include('project.api.urls', namespace='api')),

aPIアプリレベルの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を変更して正しいコードに切り替えるミドルウェアを作成します。プロジェクトレベルのURLで定義された名前空間( 'api')は柔軟ではなく、ミドルウェアで認識される必要があることに注意してください。

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/
38
James Lin