Django REST framework 版本

API 版本控制允許我們在不同的客戶端之間更改行為(同一個接口的不同版本會返回不同的數據)。 DRF提供了許多不同的版本控制方案。

可能會有一些客戶端因為某些原因不再維護了,但是我們后端的接口還要不斷的更新迭代,這個時候通過版本控制返回不同的內容就是一種不錯的解決方案。

DRF提供的版本控制方案

DRF提供了五種版本控制方案,如下圖:

?

版本控制系統的使用

全局配置

這里我們以?URLPathVersioning 為例,還是在項目的settings.py中REST_FRAMEWORK配置項下配置:

REST_FRAMEWORK = {...'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning','DEFAULT_VERSION': 'v1',           # 默認的版本'ALLOWED_VERSIONS': ['v1', 'v2'],  # 有效的版本'VERSION_PARAM': 'version',        # 版本的參數名與URL conf中一致
}

局部配置

注意,通常我們是不會單獨給某個視圖設置版本控制的,如果你確實需要給單獨的視圖設置版本控制,你可以在視圖中設置versioning_class屬性,如下:

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

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'})),]

我們在視圖中可以通過訪問?request.version?來獲取當前請求的具體版本,然后根據不同的版本來返回不同的內容:

我們可以在視圖中自定義具體的行為,下面以不同的版本返回不同的序列化類為例

class PublisherViewSet(ModelViewSet):def get_serializer_class(self):"""不同的版本使用不同的序列化類"""if self.request.version == 'v1':return PublisherModelSerializerVersion1else:return PublisherModelSerializerqueryset = models.Publisher.objects.all()

REST framework 提供的默認版本的源碼

############################## versioning.py #############################
# coding: utf-8
from __future__ import unicode_literalsimport refrom django.utils.translation import ugettext_lazy as _from rest_framework import exceptions
from rest_framework.compat import unicode_http_header
from rest_framework.reverse import _reverse
from rest_framework.settings import api_settings
from rest_framework.templatetags.rest_framework import replace_query_param
from rest_framework.utils.mediatypes import _MediaType# 基礎類,其他類要繼承此類
class BaseVersioning(object):default_version = api_settings.DEFAULT_VERSION           # 配置文件中獲取相應信息allowed_versions = api_settings.ALLOWED_VERSIONSversion_param = api_settings.VERSION_PARAMdef 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 Truereturn ((version is not None and version == self.default_version) or(version in self.allowed_versions))# 版本信息在頭部
class AcceptHeaderVersioning(BaseVersioning):"""GET /something/ HTTP/1.1Host: example.comAccept: application/json; version=1.0"""invalid_version_message = _('Invalid version in "Accept" header.')def determine_version(self, request, *args, **kwargs):media_type = _MediaType(request.accepted_media_type)version = media_type.params.get(self.version_param, self.default_version)version = unicode_http_header(version)if not self.is_allowed_version(version):raise exceptions.NotAcceptable(self.invalid_version_message)return version# We don't need to implement `reverse`, as the versioning is based# on the `Accept` header, not on the request URL.# 版本信息在url中
class URLPathVersioning(BaseVersioning):"""To the client this is the same style as `NamespaceVersioning`.The difference is in the backend - this implementation usesDjango'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.1Host: example.comAccept: 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 version is None:version = self.default_versionif not self.is_allowed_version(version):raise exceptions.NotFound(self.invalid_version_message)return versiondef reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):if request.version is not None:kwargs = {} if (kwargs is None) else kwargskwargs[self.version_param] = request.versionreturn super(URLPathVersioning, self).reverse(viewname, args, kwargs, request, format, **extra)class NamespaceVersioning(BaseVersioning):"""To the client this is the same style as `URLPathVersioning`.The difference is in the backend - this implementation usesDjango's URL namespaces to determine the version.An example URL conf that is namespaced into two separate versions# users/urls.pyurlpatterns = [url(r'^/users/$', users_list, name='users-list'),url(r'^/users/(?P<pk>[0-9]+)/$', users_detail, name='users-detail')]# urls.pyurlpatterns = [url(r'^v1/', include('users.urls', namespace='v1')),url(r'^v2/', include('users.urls', namespace='v2'))]GET /1.0/something/ HTTP/1.1Host: example.comAccept: application/json"""invalid_version_message = _('Invalid version in URL path. Does not match any version namespace.')def determine_version(self, request, *args, **kwargs):resolver_match = getattr(request, 'resolver_match', None)if resolver_match is None or not resolver_match.namespace:return self.default_version# Allow for possibly nested namespaces.possible_versions = resolver_match.namespace.split(':')for version in possible_versions:if self.is_allowed_version(version):return versionraise exceptions.NotFound(self.invalid_version_message)def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):if request.version is not None:viewname = self.get_versioned_viewname(viewname, request)return super(NamespaceVersioning, self).reverse(viewname, args, kwargs, request, format, **extra)def get_versioned_viewname(self, viewname, request):return request.version + ':' + viewnameclass HostNameVersioning(BaseVersioning):"""GET /something/ HTTP/1.1Host: v1.example.comAccept: application/json"""hostname_regex = re.compile(r'^([a-zA-Z0-9]+)\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+$')invalid_version_message = _('Invalid version in hostname.')def determine_version(self, request, *args, **kwargs):hostname, separator, port = request.get_host().partition(':')match = self.hostname_regex.match(hostname)if not match:return self.default_versionversion = match.group(1)if not self.is_allowed_version(version):raise exceptions.NotFound(self.invalid_version_message)return version# We don't need to implement `reverse`, as the hostname will already be# preserved as part of the REST framework `reverse` implementation.# 通過url參數區分
class QueryParameterVersioning(BaseVersioning):"""GET /something/?version=0.1 HTTP/1.1Host: example.comAccept: application/json"""invalid_version_message = _('Invalid version in query parameter.')def determine_version(self, request, *args, **kwargs):version = request.query_params.get(self.version_param, self.default_version)if not self.is_allowed_version(version):raise exceptions.NotFound(self.invalid_version_message)return versiondef reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):url = super(QueryParameterVersioning, self).reverse(viewname, args, kwargs, request, format, **extra)if request.version is not None:return replace_query_param(url, self.version_param, request.version)return url

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/454427.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454427.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454427.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AngularJS中的過濾器(filter)

AngularJS中的過濾器是用于對數據的格式化&#xff0c;或者篩選的函數&#xff0c;可以直接通過以下語法使用&#xff1a; {{expression|filter}} {{expression|filter1|filter2}} {{expression|filter1:param1,param2,...|filter2} 過濾器的種類有number&#xff0c;currency&…

計算機考試上傳照片教程,電腦照片傳到iPhone手機的詳細步驟【圖文】

蘋果自帶的iOS系統是不可以隨便和電腦進行數據交換的&#xff0c;必須使用iTunes軟件。許多用戶為此問題困擾&#xff0c;我們有什么可以把電腦照片傳到iPhone手機&#xff1f;下面我們就一起來看看把電腦照片傳到iphone設備的詳細步驟。具體方法如下&#xff1a;1&#xff0c;…

javaweb 導出文件名亂碼的問題解決方案

fileName new String(fileName.getBytes("ISO8859-1"), "UTF-8"); 或者 String finalFileName null; if(StringUtils.contains(userAgent, "MSIE")){//IE瀏覽器 finalFileName URLEncoder.encode(fileName,"UTF8"); }else if(Str…

AVS 分像素運動估計優化算法

—249—AVS 分像素運動估計優化算法楊涵悅 1&#xff0c;張兆楊1&#xff0c;滕國偉2(1. 上海大學通信學院&#xff0c;上海 200072&#xff1b;2. 上海廣電(集團)有限公司中央研究院&#xff0c;上海 200233)摘要&#xff1a;針對AVS 分像素運動估計的問題&#xff0c;提出一種…

計算機系統結構sw指令集,自考02325計算機系統結構復習資料六

自考生網為考生收集整理了“自考02325計算機系統結構復習資料六“以供考生們在考試前用復習資料鞏固所學到的知識&#xff0c;得到更好地復習效果。注&#xff1a;由于各省教材每年都有更新、變動&#xff0c;自考復習資料并不一定出于同一自考教材版本&#xff0c;但考生們仍可…

Django REST framework 源碼中提供的默認配置

DEFAULTS 是默認配置&#xff0c;IMPORT_STRINGS 是要相對應導入的類 鍵 大寫大寫大寫 ########################### settings.py ########################## DEFAULTS {# Base API policiesDEFAULT_RENDERER_CLASSES: (rest_framework.renderers.JSONRenderer,rest_framew…

python 去掉空格_如何從Python DataFrame中去除空格在這個例子中

使用applymap到數據幀&#xff0c;applymap施加一拉每個單元格上的mbda函數。在lambda函數中拆分字符串&#xff08;白色空格在其中被忽略&#xff09;然后加入它。如果有一個int&#xff0c;那么你可以在lambda函數中使用if else。 from pandas import Series, DataFrame impo…

Mware HA實戰攻略之五VMwareHA測試驗收

【IT168 專稿】在上一篇"VMware HA實戰攻略之四VMwareHA安裝及配置"中&#xff08;點擊&#xff09;&#xff0c;講述了VMwareHA的概念及創建過程&#xff0c;還講述了創建過程中要注意的一些事項。在本篇中&#xff0c;將要講述如何在群集節點之一的ESX主機上安裝虛…

AVS解碼器在DSP平臺上的優化

AVS( Audio Video Coding STandard)是由我國數字 音視頻標準工作組制定的具有自主知識產權的第二代音視頻壓縮準。AVS實行1 元專利費用的原則&#xff0c;相比其它音視頻編解碼標準具有編碼效率高、專利費用低、授權模式簡單等優勢。AVS 解碼器的結構復雜、運算量較大&#xff…

如何重做計算機系統軟件,電腦卡如何一鍵重做Win7旗艦版

電腦卡如何一鍵重做Win7旗艦版&#xff1f;小伙伴們在使用電腦的過程中系統會越來越卡&#xff0c;對于新手小白來說怎么重裝系統是一個比較煩惱的問題&#xff0c;不知道如何下手&#xff0c;從哪里開始&#xff0c;那么接下來就以云騎士裝機大師為例給小伙伴們講解一下電腦卡…

Django Rest framework Request

[Django Rest framework文檔翻譯]-Request REST framework的Request類擴展自標準的HttpRequest&#xff0c;增加了REST framework靈活的請求解析和請求驗證支持。 請求解析 REST framework的Request對象提供了靈活的請求解析&#xff0c;讓你可以像一般處理普通form數據一樣…

python去停用詞用nltk_【NLTK】安裝和使用NLTK分詞和去停詞

黃聰&#xff1a;PythonNLTK自然語言處理學習&#xff08;一&#xff09;&#xff1a;環境搭建 http://www.cnblogs.com/huangcong/archive/2011/08/29/2157437.html 安裝NLTK可能出現的問題&#xff1a; 1. pip install ntlk 2. 如果遇到缺少stopwords報錯如下&#xff1a;&am…

JavaScript知識概要

JavaScript 1.簡介 JavaScript簡介&#xff1a; JS是運行在瀏覽器端的一門腳本語言&#xff0c;一開始主要用來做瀏覽器驗證&#xff0c;但現在功能已經不止于此。 所謂腳本語言就是指&#xff0c;代碼不需要編譯&#xff0c;直接運行&#xff0c;并且讀入…

計算機文檔xsl,XSL-FO 文檔

XSL-FO 文檔XSL-FO 文檔XSL-FO 文檔是帶有輸出信息的 XML 文件。XSL-FO 文檔存儲在以 .fo 或 .fob 為文件擴展名的文件中。您也可以把 XSL-FO 文檔存儲為以 .xml 為擴展名的文件&#xff0c;這樣做的話可以使 XSL-FO 文檔更易被 XML 編輯器存取。XSL-FO 文檔結構XSL-FO 的文檔結…

vue項目cordova打包的android應用

準備工作nodejs、cordova、AndroidStudio這些在上一篇文章中已經說過了&#xff0c;這里就不重復說明。以此文記錄vue項目用cordova打包移動app的方法。 1.創建一個cordova項目&#xff0c;如創建一個名為testapp的工程&#xff1a;cordova create testapp 2.添加安卓平臺 cord…

H.264視頻開發---代碼移植

基于DSP系統開發的視頻編解碼系統&#xff0c;國內幾乎都是走的移植&#xff0c;優化的路線&#xff0c;并且移植的代碼&#xff0c;都是開源的。畢竟花費大量的人力&#xff0c;物力去開發一套自己的代碼&#xff0c;并不見得比一些成熟的開源代碼效率更高&#xff0c;健壯性更…

Django REST framework 源碼解析

先放圖&#xff0c;放圖說話&#xff0c;可能有點長 主流程 這個顏色 從setting導入默認數據流程是 這個顏色 主流程大概流程寫一下&#xff1a;as_view 實際返回view&#xff0c;并把參數{"get":"list","post":"create"}傳遞給view…

-9 逆序輸出一個整數的各位數字_leetcode兩數相加(大整數相加)

題目來源于leetcode第二題兩數相加。題目描述給出兩個非空的鏈表用來表示兩個非負的整數。其中&#xff0c;它們各自的位數是按照逆序的方式存儲的&#xff0c;并且它們的每個節點只能存儲一位數字。如果&#xff0c;我們將這兩個數相加起來&#xff0c;則會返回一個新的鏈表來…

計算機如何添加管理員權限,電腦使用代碼如何添加管理員權限

我們在使用電腦運行某些軟件的時候&#xff0c;可能需要用到管理員權限才能運行&#xff0c;通常來說直接點擊右鍵就會有管理員權限&#xff0c;但最近有用戶向小編反饋&#xff0c;在需要管理員權限的軟件上點擊右鍵沒有看到管理員取得所有權&#xff0c;那么究竟該如何才能獲…

mysql選擇數據庫創建數據庫

MySQL 選擇數據庫 在你連接到 MySQL 數據庫后&#xff0c;可能有多個可以操作的數據庫&#xff0c;所以你需要選擇你要操作的數據庫。 從命令提示窗口中選擇MySQL數據庫 在 mysql> 提示窗口中可以很簡單的選擇特定的數據庫。你可以使用SQL命令來選擇指定的數據庫。 實例 以下…