小谈DRF之版本控制相关

4. 版本控制 *

4.1 基于Django的版本控制的简单实现

直接看代码,如下:

# urls.py
from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^app01/', include('app01.urls')),
]
# app01.urls.py
from django.conf.urls import url
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^users/$', views.UsersView.as_view()),
]
# views.py
from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from rest_framework.request import Request
# Create your views here.

class UsersView(APIView):

    def get(self, request, *args, **kwargs):
        print(request._request.GET.get('version'))
        print(request.query_params.get('version'))
        # request._request.GET和request.query_params是等价的,可以查看Request的源码
        return HttpResponse('用户列表')

在浏览器地址栏中输入:http://127.0.0.1:8000/app01/users/?version=v1后,看显示效果:

在浏览器中的显示如下:

image-20200913132257592

在控制台的显示效果如下:

image-20200913132328682

其中:request._request.GETrequest.query_params是等价的,可以查看Request的源码,如下:

image-20200913132546113

4.2 基于rest framework的版本控制的简单实现

4.2.1 URL中通过GET传参(自定义)

url:http://127.0.0.1:8000/app01/users/?version=v1

其他代码一样,直接看views.py中的代码:

from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.versioning import BaseVersioning


class ParamVersion(object):

    def determine_version(self, request, *args, **kwargs):
        return request.query_params.get('version')


class UsersView(APIView):

    versioning_class = ParamVersion

    def get(self, request, *args, **kwargs):
        # print(request._request.GET.get('version'))
        # print(request.query_params.get('version'))
        print(request.version)
        return HttpResponse('用户列表')

效果和上面是一样的。

4.2.2 URL中通过GET传参(使用内置的)

from rest_framework.versioning import BaseVersioning, QueryParameterVersioning

class UsersView(APIView):

    versioning_class = QueryParameterVersioning

    def get(self, request, *args, **kwargs):
        print(request.version)
        return HttpResponse('用户列表')

效果和上面也是一样的。

查看QueryParameterVersioning的源码,如下:

image-20200913142657368

通过查看其源码,我们可以知道在QueryParameterVersioning的 内部帮我们实现了上述功能,而且有三个配置项:

REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v2', # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本
    'VERSION_PARAM': 'version' # 在浏览器中?version中的version,可以修改
}

4.2.3 在URL的路径中传参(推荐使用)

url:http://127.0.0.1:8000/app01/v1/users/

# app01.urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^(?P<version>[v1|v2]+)/users/$', views.UsersView.as_view()),
]
# views.py
from rest_framework.versioning import BaseVersioning, QueryParameterVersioning, URLPathVersioning

class UsersView(APIView):

    versioning_class = URLPathVersioning

    def get(self, request, *args, **kwargs):
        print(request.version)
        return HttpResponse('用户列表')

查看URLPathVersioning的源码,我们就知道如何写url的正则了:

image-20200913144401908

4.4 全局配置

版本控制这种操作基本上都是全局配置一次就可以了,所以下面看全局配置:

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
    'DEFAULT_VERSION': 'v2', # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本
    'VERSION_PARAM': 'version' # 在浏览器中?version中的version,可以修改
}
# views.py
from restframework.views import APIView

class UsersView(APIView):

    def get(self, request, *args, **kwargs):
        print(request.version)
        return HttpResponse('用户列表')
# urls.py
from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^app01/', include('app01.urls')),
]
# app01.urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^(?P<version>[v1|v2]+)/users/$', views.UsersView.as_view()),
]

这样配置好后,我们在浏览器输入http://127.0.0.1:8000/app01/v1/users/后,在控制台就会显示正常的版本;

4.5 全局配置源码分析

点开APIView的源码后就能看出来:

image-20200913145135382

4.6 源码流程分析

点开dispatch()方法,查看其源码:

image-20200913145702983

继续点开initial()方法,查看其源码:

image-20200913145751089

通过查看initial()方法的源码,我们发现:在做认证、权限和节流之前做的版本控制操作;

现在继续看版本控制的源码,点开self.determine_version()方法,查看其源码:

image-20200913150150665

4.7 反向生成URL

# app01.urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^(?P<version>[v1|v2]+)/users/$', views.UsersView.as_view(), name='uuu'),
]
from rest_framework.views import APIView
from django.urls import reverse

class UsersView(APIView):

    def get(self, request, *args, **kwargs):
        # 获取到的版本号
        print(request.version)
        # 版本控制类对象
        print(request.versioning_scheme)

        # 反向生成URL(基于restframework)
        u1 = request.versioning_scheme.reverse(viewname='uuu', request=request)
        print(u1)

        # 反向生成URL(基于Django内置的)
        u2 = reverse(viewname='uuu', kwargs={'version': 'v1'})
        print(u2)

        return HttpResponse('用户列表')

可以看到控制台显示如下:

image-20200913155001838

此时的浏览器:

image-20200913155039355

我们点开from rest_framework.versioning import BaseVersioning, QueryParameterVersioning, URLPathVersioning中的任何一个类,都会发现有一个reverse()方法,查看其源码:

image-20200913155354870

4.8 版本控制内置类

查看源码:

image-20200913160224131

我们不仅可以通过URL中GET传参、URL路径传参获取版本,还可以通过请求头、namespace、子域名等获取版本号,都不是很常用,需要时可以自己看,看各个类中的注释就能大致了解。

posted @ 2020-10-19 23:01  richard_A  阅读(79)  评论(0编辑  收藏  举报