欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

DRF框架API版本管理實現(xiàn)方法解析

 更新時間:2020年08月21日 10:14:06   作者:削微寒  
這篇文章主要介紹了DRF框架API版本管理實現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

API 不可能一成不變,無論是新增或者刪除已有 API,都會對調(diào)用它的客戶端產(chǎn)生影響。如果對 API 的增刪沒有管理,隨著 API 的增增減減,調(diào)用它的客戶端就會逐漸陷入迷茫,到底哪個 API 是可用的?為什么之前可用的 API 又不可用了,新增了哪些 API 可以使用?為了方便 API 的管理,我們引入版本功能。

給 API 打上版本號,在某個特定版本下,原來已有的 API 總是可用的。如果要對 API 做重大變更,可以發(fā)布一個新版本的 API,并及時提醒用戶 API 已變更,敦促用戶遷移到新的 API,這樣可以給客戶端提供一個緩沖過渡期,不至于昨天能用的 API,今天突然報錯了。

django-rest-framework 提供了多個 API 版本輔助類,分別實現(xiàn)不同的 API 版本管理方式。比較實用的有:

AcceptHeaderVersioning

這個類要求客戶端在 HTTP 的 Accept 請求頭加上版本號以表明想請求的 API 版本,例如如下請求:

GET /bookings/ HTTP/1.1
Host: example.com
Accept: application/json; version=1.0

這將請求版本號為 1.0 的接口。

URLPathVersioning

這個類要求客戶端在請求的 url 中指定版本號,一個缺點是你在書寫 URL 模式時,必須包含關鍵字為 version 的模式,例如官網(wǎng)的一個例子:

urlpatterns = [
  url(
    r'^(?P<version>(v1|v2))/bookings/$',
    bookings_list,
    name='bookings-list'
  ),
  url(
    r'^(?P<version>(v1|v2))/bookings/(?P<pk>[0-9]+)/$',
    bookings_detail,
    name='bookings-detail'
  )
]

這樣的話很不方便,因此我們一般不使用。

NamespaceVersioning

和上面提到的 URLPathVersioning 類似,只不過版本號不是在 URL 模式中指定,而是通過 namespace 參數(shù)指定 (稍后我們將看到它的具體用法)。

當然,django-rest-framework 還提供了其它諸如 HostNameVersioning、QueryParameterVersioning 的版本管理輔助類,可自行查看文檔了解:https://www.django-rest-framework.org/api-guide/versioning/

綜合來看,NamespaceVersioning 模式便于 URL 的設計與管理,因此我們的博客應用決定采用這種 API 版本管理方式。

為了開啟 api 版本管理,在項目的配置中加入如下配置:

settings/common.py
REST_FRAMEWORK = {
  'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning',
  'DEFAULT_VERSION': 'v1'
}

以上兩項設置分別全局指定使用的 API 版本管理方式和客戶端缺省版本號的情況下默認請求的 API 版本。盡管這些配置項也可以在單個視圖或者視圖集的范圍內(nèi)指定,但是,統(tǒng)一的版本管理模式更為可取,因此我們在全局配置中指定。

接著在注冊的 API 接口前帶上版本號:

blogproject/urls.py
urlpatterns = [
  # ...
  path("api/v1/", include((router.urls, "api"), namespace="v1")),
]

注意這里比之前多了個 namespace 參數(shù),參數(shù)值為 v1,代表包含的 URL 模式均屬于 v1 這個命名空間。還有一點需要注意,對于 include 函數(shù),如果指定了 namespace 的值,第一個參數(shù)必須是一個元組,形式為:(url_patterns, app_name),這里我們將 app_name 指定為 api。

一旦我們開啟了版本管理,所有請求對象 request 就會多出一個屬性 version,其值為用戶請求的版本號(如果沒有指定,就為默認的 DEFAULT_VERSION 的值)。因此,我們可以在請求中針對不同版本的請求執(zhí)行不同的代碼邏輯。比如我們的博客修改文章列表 API,序列化器對返回數(shù)據(jù)的字段做了一些改動,發(fā)布在版本 v2,那么可以根據(jù)用戶用戶請求的版本,返回不同的數(shù)據(jù),即新增了 API,又保持對原 api 的兼容:

if request.version == 'v1':
	return PostSerializerV1()
return PostSerializer

if 分支可以視為一段臨時代碼,我們可以通過適當?shù)姆绞教嵝延脩?,API 已經(jīng)更改,請盡快遷移到新的版本 v2,并且在未來的某個時間,確認大部分用戶都成功遷移到新版api后移除掉這些代碼,并將默認版本設為v2,這樣原本的 v1 版本的 API 就徹底被廢棄了。

當然,我們目前的博客接口還暫時沒有需要修改升級的地方,不過為了測試 API 版本管理的設置是否生效了,我們認為添加一個測試用的視圖集,在里面做針對不同版本請求的處理,看看不同版本的請求下是否會返回符合預期的不同內(nèi)容。

首先在 blog/views.py 中加一個簡單的測試視圖集,這個視圖集中有個測試用的接口,接口處理邏輯是根據(jù)不同的版本號,返回不同的內(nèi)容:

class ApiVersionTestViewSet(viewsets.ViewSet):
  @action(
    methods=["GET"], detail=False, url_path="test", url_name="test",
  )
  def test(self, request, *args, **kwargs):
    if request.version == "v1":
      return Response(
        data={
          "version": request.version,
          "warning": "該接口的 v1 版本已廢棄,請盡快遷移至 v2 版本",
        }
      )
    return Response(data={"version": request.version})

當然視圖集別忘了在 router 中注冊:

blogproject/urls.py

blogproject/urls.py

# 僅用于 API 版本管理測試
router.register(
  r"api-version", blog.views.ApiVersionTestViewSet, basename="api-version"
)

這相當于一次接口版本升級,我們再加入 v2 命名空間的接口:

urlpatterns = [
  path("api/v1/", include((router.urls, "api"), namespace="v1")),
  path("api/v2/", include((router.urls, "api"), namespace="v2")),
]

可以看到,包含的 URL 都是一樣的,只是 namespace 是 v2。

來測試一下效果,啟動開發(fā)服務器,先訪問版本號為 v1 的測試接口,請求返回結果如下,可以看到如期返回了 v1 版本下的內(nèi)容:

GET /api/v1/api-version/test/
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
  "version": "v1",
  "warning": "該接口的 v1 版本已廢棄,請盡快遷移至 v2 版本"
}

再訪問版本號為 v2 的測試接口,返回的內(nèi)容就是 v2 了。

GET /api/v2/api-version/test/

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
  "version": "v2"
}

對于其它接口,無論 v1,v2 版本的接口均可以訪問,這樣就相當于完成了一次兼容的接口升級。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Python進階_關于命名空間與作用域(詳解)

    Python進階_關于命名空間與作用域(詳解)

    下面小編就為大家?guī)硪黄狿ython進階_關于命名空間與作用域(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • Python+wxPython實現(xiàn)個人鏈接收藏夾

    Python+wxPython實現(xiàn)個人鏈接收藏夾

    這篇文章主要介紹了如何使用wxPython和XML數(shù)據(jù)源創(chuàng)建一個具有按鈕和Web視圖的應用程序窗口,以便輕松管理和訪問各種網(wǎng)頁鏈接,感興趣的可以了解下
    2023-08-08
  • 淺談Python數(shù)學建模之整數(shù)規(guī)劃

    淺談Python數(shù)學建模之整數(shù)規(guī)劃

    整數(shù)規(guī)劃并不一定是線性規(guī)劃問題的變量取整限制,對于二次規(guī)劃、非線性規(guī)劃問題也有變量取整限制而引出的整數(shù)規(guī)劃。但在數(shù)學建模問題中所說的整數(shù)規(guī)劃,通常是指整數(shù)線性規(guī)劃。整數(shù)規(guī)劃與線性規(guī)劃的差別只是變量的整數(shù)約束。選擇簡單通用的編程方案,讓求解器去處理吧
    2021-06-06
  • 使用python實現(xiàn)接口的方法

    使用python實現(xiàn)接口的方法

    接口只是定義了一些方法,而沒有去實現(xiàn),多用于程序設計時,只是設計需要有什么樣的功能,但是并沒有實現(xiàn)任何功能,這些功能需要被另一個類(B)繼承后,由 類B去實現(xiàn)其中的某個功能或全部功能。
    2017-07-07
  • Python如何通過變量ID得到變量的值

    Python如何通過變量ID得到變量的值

    這篇文章主要介紹了Python如何通過變量ID得到變量的值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • python實現(xiàn)拉普拉斯特征圖降維示例

    python實現(xiàn)拉普拉斯特征圖降維示例

    今天小編就為大家分享一篇python實現(xiàn)拉普拉斯特征圖降維示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • 詳解Python 3D引擎Ursina如何繪制立體圖形

    詳解Python 3D引擎Ursina如何繪制立體圖形

    Python有一個不錯的3D引擎——Ursina。本文就來手把手教你認識Ursina并學會繪制立體圖形,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-01-01
  • 基于Python fminunc 的替代方法

    基于Python fminunc 的替代方法

    今天小編就為大家分享一篇基于Python fminunc 的替代方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • Python開發(fā)實例分享bt種子爬蟲程序和種子解析

    Python開發(fā)實例分享bt種子爬蟲程序和種子解析

    最近瘋狂的研究DHT網(wǎng)絡技術,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2014-05-05
  • 在Django中使用Sitemap的方法講解

    在Django中使用Sitemap的方法講解

    這篇文章主要介紹了在Django中使用Sitemap的方法講解,Django是最具人氣的Python web開發(fā)框架,需要的朋友可以參考下
    2015-07-07

最新評論