Django Rest Framework之版本控制

基本代碼結構

settings.py:前端

REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v1',            # 默認版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],   # 容許的版本
    'VERSION_PARAM': 'version'          # URL中獲取值的key
}

 urls.py:python

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/test/', TestView.as_view(), name='test'),
]

 views.py:web

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning


class TestView(APIView):
    versioning_class = URLPathVersioning

    def get(self, request, *args, **kwargs):
        # 獲取版本
        print(request.version)
        # 獲取版本管理的類
        print(request.versioning_scheme)

        # 反向生成URL
        reverse_url = request.versioning_scheme.reverse('test', request=request)
        print(reverse_url)

        return Response('GET請求,響應內容')

    def post(self, request, *args, **kwargs):
        return Response('POST請求,響應內容')

    def put(self, request, *args, **kwargs):
        return Response('PUT請求,響應內容')

源碼分析

  • 爲何會用「versioning_class」屬性變量,它有什麼用?

  

  仍是要從APIView類中的dispatch開始提及,跟以前講的認證等功能接口同樣,首先要完成對django原生request的封裝,而後一樣是在initial方法中實現版本控制。在initial方法中能夠看到,是經過調用determine_version方法實現版本控制。正則表達式

  

  

  在determine_version方法中就能夠看到versioning_class屬性變量,再跳轉到version_class定義的地方。能夠看到,它的初始值是經過配置文件設置的,而這種方式,主要是來實現全局配置的(下文會說明全局配置)。經過全局配置和「scheme = self.versioning_class()」代碼能夠看出,這段代碼是在作對象的實例化,因此version_class屬性變量存儲的是一個對象,具體是哪一個對象,全局配置方法中告訴了咱們。使用的就是基本代碼結構中的「URLPathVersioning」對象。而這個類就是實現版本控制核心代碼的類。當咱們不使用全局配置時,那麼咱們就必須在自定義的視圖類中給version_class屬性變量賦值,即:version_class = URLPathVersioning。django

  • 在urls.py文件中,版本的正則爲何要寫成「(?P<version>[v1|v2]+)」的形式,爲何正則中的變量是「version」?

  

  跳轉到URLPathVersioning類定義的地方能夠看到,這種樣式的正則「(?P<version>[v1|v2]+)」url的編寫方式是在源碼中已經規定好的,因此咱們要使用源碼中提供的接口。源碼分析

  • 在settings配置文件中,爲何會使用「DEFUALT_VERSION」,「ALLOWED_VERSION」,「VERSION_PARM」者三個key值來作版本配置?

     

  由URLPathVersioning類的定義能夠看出,它的父類是BaseVersioning類,先看一下這個類的具體定義。最開始定義的三個屬性變量「default_version」,「allowed_versions」,「version_param」的值,也都是經過settings配置文件賦值的,而這三個值不就是問題中提到的三個key值嗎?post

  再看determine_version方法,它會拋出異常,因此它的子類(URLPathVersioning類)必須重寫這個方法。而下面的is_allowed_version方法,就是用來判斷前端請求的版本號是不是配置文件中所配置的版本之一,這就用到了allowed_versions屬性變量。若是沒有配置allowed_versions變量(也就是說沒有設置版本控制的功能,那天然是容許經過的,返回True),若是作了版本控制,那麼就要判斷當前獲取的版本號(version變量)是否在配置的版本中,這裏就會用到default_version變量和allowed_versions變量。url

  reverse方法是用於URL反射用的,這裏就很少談了。spa

      

  再回到URLPathVersioning類中,能夠看到determine_version方法。在這個方法中能夠看到,經過kwargs.get()來獲取前端請求時的版本號,這就要用到version_param和default_version變量。值得注意的是在對version_param變量配置時,的字符串必須跟在urls.py中的正則表達式中的變量保存一致(這裏用的是「version」字符串)。當version變量爲None時,就使用默認的版本。以後再調用is_allowed_version方法,完成對當前版本的是否合法的判斷。最後返回合法的版本號。版本控制

  

      

  再回到APIView類中的initial方法中,能夠看到它也調用了本身的determine_version方法。在determine_version方法中,能夠看到上文提到過的versioning_class屬性變量,它保存了URLPathVersion類對象。再看determine_version方法的返回值,返回的是一個元組。元組第一個元素正是上文提到過的URLPathVersion類中的determine_version方法,而這個方法返回的也正是合法的版本號。元組第二個元素是就是這個版本類對象。

  再來到initial方法中,determine_version方法返回的元組的值,分別賦值到了request.version和request_versioning_scheme變量中。所以,在代碼基本結構中,經過request.version變量來獲取合法的版本號。

全局配置

REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",
    'DEFAULT_VERSION': 'v1',
    'ALLOWED_VERSIONS': ['v1', 'v2'],
    'VERSION_PARAM': 'version' 
}

   當使用全局配置時,就不須要在自定義的視圖類中使用「versioning_class = URLPathVersioning」這段代碼了。

相關文章
相關標籤/搜索