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.mzph.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命令来选择指定的数据库。 实例 以下…