• 06 Django REST Framework 版本控制


     01-版本控制

    对接口进行版本控制只是一种杀死已部署客户端的“礼貌”方式。
    - 罗伊菲尔丁。
    
    1. API版本控制允许您更改不同客户端之间的行为。REST框架提供了许多不同的版本控制方案。
    
    2. 版本控制由传入的客户端请求确定,可以基于请求URL,也可以基于请求标头。
    
    3. 有许多有效的方法来处理版本控制。非版本化系统也是合适的,特别是如果您正在为具有多个客户端的长期系统进行工程设计。

    02-版本控制方案

    详解:https://www.django-rest-framework.org/api-guide/versioning/

    03-版本控制的使用

    3.1 全局配置

    这里我们以 URLPathVersioning 为例,还是在项目的settings.py中REST_FRAMEWORK配置项下配置:

    REST_FRAMEWORK = {
        ...
        # 去url路径里面获取版本
        'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
        'DEFAULT_VERSION': 'v1',              # 默认的版本
        'ALLOWED_VERSIONS': ['v1', 'v2'],  # 允许的版本
        'VERSION_PARAM': 'version',  # 版本的参数名与URL conf中一致
    }

    urls.py

    urlpatterns = [
        ...
        url(r'^(?P<version>[v1|v2]+)/publishers/$', views.PublisherViewSet.as_view({'get': 'list', 'post': 'create'})),
        url(r'^(?P<version>[v1|v2]+)/publishers/(?P<pk>d+)/$', views.PublisherViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
    
    ]

    我们可以在视图中自定义具体的行为,下面以不同的版本返回不同的序列化类为例:

    class PublisherViewSet(ModelViewSet):
    
        queryset = models.Publisher.objects.all()
    
        def get_serializer_class(self):
            """不同的版本使用不同的序列化类"""
            # request.version:获取版本
            if self.request.version == 'v1':
                return PublisherModelSerializerVersion1
            else:
                return PublisherModelSerializer

    3.2 局部配置

    注意,通常我们是不会单独给某个视图设置版本控制的,如果你确实需要给单独的视图设置版本控制,你可以在视图中设置versioning_class属性,如下:

    class PublisherViewSet(ModelViewSet):
    
        ...
        versioning_class = URLPathVersioning

    04-反向解析url

    # api/urls.py
    
    from django.urls import path,re_path
    from .views import UserView
    
    urlpatterns = [
        re_path('(?P<version>[v1|v2]+)/users/', UserView.as_view(),name = 'api_user'),
    ]
    # api/views.py
    
    from django.shortcuts import render,HttpResponse
    from rest_framework.views import APIView
    from rest_framework.request import Request
    
    class UserView(APIView):
    
        def get(self,request,*args,**kwargs):
            #获取版本
            print(request.version)
            #获取处理版本的对象
            print(request.versioning_scheme)
            #获取浏览器访问的url,reverse反向解析
            #需要两个参数:viewname就是url中的别名,request=request是url中要传入的参数
            #(?P<version>[v1|v2]+)/users/,这里本来需要传version的参数,但是version包含在request里面(源码里面可以看到),所有只需要request=request就可以
            url_path = request.versioning_scheme.reverse(viewname='api_user',request=request)
            print(url_path)
            # self.dispatch
            return HttpResponse('用户列表')

    05-versioning_class

    06-URLPathVersioning源码

    class URLPathVersioning(BaseVersioning):
        """
        To the client this is the same style as `NamespaceVersioning`.
        The difference is in the backend - this implementation uses
        Django's URL keyword arguments to determine the version.
    
        An example URL conf for two views that accept two different versions.
    
        urlpatterns = [
            url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
            url(r'^(?P<version>[v1|v2]+)/users/(?P<pk>[0-9]+)/$', users_detail, name='users-detail')
        ]
    
        GET /1.0/something/ HTTP/1.1
        Host: example.com
        Accept: application/json
        """
        invalid_version_message = _('Invalid version in URL path.')
    
        def determine_version(self, request, *args, **kwargs):
            version = kwargs.get(self.version_param, self.default_version)
            if not self.is_allowed_version(version):
                raise exceptions.NotFound(self.invalid_version_message)
            return version
    
        def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
            if request.version is not None:
                kwargs = {} if (kwargs is None) else kwargs
                kwargs[self.version_param] = request.version
    
            return super(URLPathVersioning, self).reverse(
                viewname, args, kwargs, request, format, **extra
            )

    url配置案例:

    6.1 determine_version

    里面有个is_allowed_version,点进去可以看到一些基本参数 (继承BaseVersioning基类)

    class BaseVersioning(object):
        #默认的版本
        default_version = api_settings.DEFAULT_VERSION
        #允许的版本
        allowed_versions = api_settings.ALLOWED_VERSIONS
        #默认参数(是version,比如你可以自定义为v)
        version_param = api_settings.VERSION_PARAM
    
        def determine_version(self, request, *args, **kwargs):
            msg = '{cls}.determine_version() must be implemented.'
            raise NotImplementedError(msg.format(
                cls=self.__class__.__name__
            ))
    
        def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
            return _reverse(viewname, args, kwargs, request, format, **extra)
    
        def is_allowed_version(self, version):
            if not self.allowed_versions:
                return True
            return ((version is not None and version == self.default_version) or
                    (version in self.allowed_versions))
  • 相关阅读:
    JDBC的简单使用
    IO流知识点总结
    使用IO流实现一个简单的小Dome
    java编程实现日历
    如何用Java实现DVD的一些功能
    java 入门学习
    在mac电脑上创建java的一些简单操作
    Java Struts框架的一些问答面试题
    分层开发的思想
    JDBC连接数据库
  • 原文地址:https://www.cnblogs.com/pgxpython/p/10292076.html
Copyright © 2020-2023  润新知