DRF 版本

DRF 版本

官方文档

为什么使用版本控制

API 版本控制允许我们在不同的客户端之间更改行为(同一个接口的不同版本会返回不同的数据)。 DRF提供了许多不同的版本控制方案。

可能会有一些客户端因为某些原因不再维护了,但是后端的接口还要不断的更新迭代,这个时候通过版本控制返回不同的内容就是一种不错的解决方案。

DRF提供的版本控制方案

  1. 将版本信息放到请求头中,class AcceptHeaderVersioning(BaseVersioning):
  2. 将版本信息放到URL中,class URLPathVersioning(BaseVersioning):
  3. 通过namesplace来区分版本,class NamespaceVersioning(BaseVersioning):
    1. 与 URLPathVersioning 对于需要客户端同样需要将版本信息放到URL中,不同的是NamespaceVersioning在后端采用路由的命名空间(namespace),分配到两个不同的视图中
  4. 通过主机名来区分版本,class HostNameVersioning(BaseVersioning):
    1. 域名的二级域名
  5. 通过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

源码分析

  1. APIView中的 dispatch 方法

1561881543672

  1. APIView中的 initial 方法

1561881686306

  1. APIView中的 determine_version方法

1561882539990

  1. rest_framework.versioning.URLPathVersioningrest_framework.versioning.URLPathVersioning 中的 determine_version 方法

1561882778478

posted @ 2019-08-16 16:48  写bug的日子  阅读(108)  评论(0编辑  收藏  举报