Django REST Framework之版本控制

何謂版本控制?

爲何須要版本控制?

一個項目在升級迭代的時候,不會立馬拋棄舊的版本,甚至會出現多個版本共存同時維護的狀況,所以須要版本控制。前端

版本控制作了什麼?

版本控制作的事情很簡單,在先後端分離的狀況下,只是對請求作判斷,判斷這是哪一個版本的請求,而後將版本信息封裝入request對象中。python

自定義版本控制類

1.settings.py配置

REST_FRAMEWORK = {
    "DEFAULT_VERSIONING_CLASS": "utils.version.MyVersion", # 默認使用的版本控制類
}

2.編寫自定義版本控制類(根據請求參數)

class MyVersion(object):
    def determine_version(self, request, *args, **kwargs):
        "版本號攜帶在請求"
        version = request.query_params.get("version", "v1") # 請求參數中查找有無version字段,若是沒有默認是v1
        return version # 將版本返回

3.視圖中獲取

request.version     # 版本號
request.versioning_scheme  # 版本控制類的實例

使用DRF的版本控制類

Django REST Framework爲咱們提供了5個版本控制類,分別是五種不一樣的判斷方式,基本能知足開發需求。正則表達式

1.AcceptHeaderVersioning 將版本信息放在請求頭
2.URLPathVersioning      將版本信息放在URL中,
3.NamespaceVersioning    將版本信息放在URL中,不一樣之處在於Django路由的處理方式,使用命名空間
4.HostNameVersioning     將版本信息放在域名的最低一層
5.QueryParameterVersioning 降版本信息放在請求參數中

直接在settings中配置就能夠用:django

REST_FRAMEWORK = {
    "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.QueryParameterVersioning",
    "DEFAULT_VERSION": "v1.0.0",    # 默認的版本,當沒法從請求中獲取版本信息的時候,默認按照此版本執行
    "ALLOWED_VERSIONS": "v1.0.0, v1.1.0, v2.0.0", # 容許的版本
    "VERSION_PARAM": "ver", # 獲取版本的參數。
}

源碼分析

1.爲何用 「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。前後端分離

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

 

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

3.在settings配置文件中,爲何會使用「DEFAULT_VERSION」,"ALLOWED_VERSION","VERSION_PARM"這三個key值來作版本配置?

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

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

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

再回到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變量來獲取合法的版本號。

相關文章
相關標籤/搜索