Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python django rest框架:api版本控制_Python_Django_Rest_Api_Django Rest Framework - Fatal编程技术网

Python django rest框架:api版本控制

Python django rest框架:api版本控制,python,django,rest,api,django-rest-framework,Python,Django,Rest,Api,Django Rest Framework,因此,在谷歌上搜索似乎普遍认为在RESTURI中嵌入版本号是一种糟糕的做法和想法 即使如此,也有强烈的支持者支持这一点。 e、 g 我的问题是如何实现在django rest框架中使用accept头/内容协商的建议解决方案 它看起来像框架中的内容协商, 已配置为基于接受的MIME类型自动返回预期值。如果我开始对自定义类型使用Accept头,我将失去框架的这一优势 在框架中是否有更好的方法来实现这一点?一种方法是将版本控制指定为媒体类型的一部分 这就是GitHub所做的 您还可以在accept头中

因此,在谷歌上搜索似乎普遍认为在RESTURI中嵌入版本号是一种糟糕的做法和想法

即使如此,也有强烈的支持者支持这一点。
e、 g

我的问题是如何实现在django rest框架中使用accept头/内容协商的建议解决方案

它看起来像框架中的内容协商,
已配置为基于接受的MIME类型自动返回预期值。如果我开始对自定义类型使用Accept头,我将失去框架的这一优势


在框架中是否有更好的方法来实现这一点?

一种方法是将版本控制指定为媒体类型的一部分

这就是GitHub所做的

您还可以在accept头中包含媒体类型参数,例如
accept:application/json;version=beta
,它将成功匹配
JSONRenderer
。然后,您可以根据接受的媒体类型对视图进行编码,使其行为有所不同,请参阅

API中有很多不同的版本控制模式,我不会说对于正确的方法还存在很大的共识,但这是一种合理的可能性


2015年1月更新:3.1.0版本将提供更好的版本控制支持。请参阅[此拉动请求]

2015年3月更新:版本控制API的文档


()了解更多详细信息。

更新:

现在得到了适当的支持


您的链接提供了一些答案:

我们发现把这个版本放在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
项目URL.py:

url(r'^api/', include('project.api.urls', namespace='api')),
api应用程序级别URL.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')),
)
版本级URL.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
通过更改路径信息创建一个中间件以切换到正确的代码,请注意,在项目级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/

@詹姆斯·林给出了一个很好的回答。在对答案的评论中,@Mar0ux询问如何处理断开的
HyperlinkedRelatedField
字段

我通过将
HyperlinkedRelatedField
更改为
SerializerMethodField
并调用
reverse
来解决这个问题,非常不明显地将额外的参数
当前应用程序
传递给它

例如,我有一个应用程序'fruits_app',名称空间版本为'v1','v2'。我有水果模型的序列化程序。所以为了序列化url,我创建了一个字段

url = serializers.SerializerMethodField()
以及相应的方法:

def get_url(self, instance):
    reverse.reverse('fruits_app:fruit-detail',
        args=[instance.pk],
        request=request,
        current_app=request.version)
使用嵌套名称空间时,您需要更改并将这些名称空间添加到当前的应用程序中。例如,如果应用程序中有一个名称空间版本为“v1”、“v2”和实例名称空间为“bananas”的应用程序“fruits\u app”,则序列化水果url的方法如下所示:

def get_url(self, instance):
    reverse.reverse('fruits_app:fruit-detail',
        args=[instance.pk],
        request=request,
        current_app='bananas:{}'.format(request.version))

显然,这个问题赢得了一个受欢迎的问题徽章,我才意识到我从来没有接受过答案。谢谢你在框架上的辛勤工作,汤姆!这种方法很好,只是它会打断超链接字段(
HyperlinkedRelatedField
etc)。有什么想法吗?我还没有一个项目设置来使用
HyperlinkedRelatedField
我想如果你指定了不同的版本,你的问题可能是链接会转到默认版本?没错。我倾向于使用
Accept
header的版本控制方法,这样URL就不会发生任何变化。恐怕在版本控制被放入包中之前,没有简单的方法可以修复,所以它会为
HyperlinkedRelatedField
生成版本感知URL,那么我们把模型放在哪里呢?