DRF 版本
DRF 版本
为什么使用版本控制
API 版本控制允许我们在不同的客户端之间更改行为(同一个接口的不同版本会返回不同的数据)。 DRF提供了许多不同的版本控制方案。
可能会有一些客户端因为某些原因不再维护了,但是后端的接口还要不断的更新迭代,这个时候通过版本控制返回不同的内容就是一种不错的解决方案。
DRF提供的版本控制方案
- 将版本信息放到请求头中,
class AcceptHeaderVersioning(BaseVersioning):
- 将版本信息放到URL中,
class URLPathVersioning(BaseVersioning):
- 通过namesplace来区分版本,
class NamespaceVersioning(BaseVersioning):
- 与 URLPathVersioning 对于需要客户端同样需要将版本信息放到URL中,不同的是NamespaceVersioning在后端采用路由的命名空间(namespace),分配到两个不同的视图中
- 通过主机名来区分版本,
class HostNameVersioning(BaseVersioning):
- 域名的二级域名
- 通过URL查询参数区分版本,
class QueryParameterVersioning(BaseVersioning):
版本控制系统使用
全局配置
这里我们以 URLPathVersioning 为例,还是在项目的settings.py中REST_FRAMEWORK配置项下配置:
REST_FRAMEWORK = {
...
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
'DEFAULT_VERSION': 'v1', # 默认的版本
'ALLOWED_VERSIONS': ['v1', 'v2'], # 有效的版本
'VERSION_PARAM': 'version', # 版本的参数名与URL conf中一致
}
url.py中
urlpatterns = [
...
url(r'^(?P<version>[v1|v2]+)/books/$', views.BookListView.as_view()),
url(r'^(?P<version>[v1|v2]+)/books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),
...
]
我们在视图中可以通过访问 request.version 来获取当前请求的具体版本,然后根据不同的版本来返回不同的内容:
class BookListView(ListCreateAPIView):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
def get_serializer_class(self):
"""根据不同版本返回不同序列化类"""
if self.request.version == 'v1':
return self.serializer_class
else:
return BookBaseSerializer
def get_queryset(self):
"""根据不同版本返回不同数据量"""
if self.request.version == 'v1':
return self.queryset.all()
else:
return self.queryset.all()[:3]
局部配置
给单独每个视图增加版本控制,通常不会这样操作,可以在视图中设置versioning_class属性,如下:
class BookListView(ListCreateAPIView):
...
versioning_class = URLPathVersioning
源码分析
- APIView中的 dispatch 方法
- APIView中的 initial 方法
- APIView中的 determine_version方法
- rest_framework.versioning.URLPathVersioningrest_framework.versioning.URLPathVersioning 中的 determine_version 方法