基本代码结构

settings.py:

REST_FRAMEWORK = {
'DEFAULT_VERSION': 'v1', # 默认版本
'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本
'VERSION_PARAM': 'version' # URL中获取值的key
}

urls.py:

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:

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。

  • 在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值吗?

  再看determine_version方法,它会抛出异常,所以它的子类(URLPathVersioning类)必须重写这个方法。而下面的is_allowed_version方法,就是用来判断前端请求的版本号是否是配置文件中所配置的版本之一,这就用到了allowed_versions属性变量。如果没有配置allowed_versions变量(也就是说没有设置版本控制的功能,那自然是允许通过的,返回True),如果做了版本控制,那么就要判断当前获取的版本号(version变量)是否在配置的版本中,这里就会用到default_version变量和allowed_versions变量。

  reverse方法是用于URL反射用的,这里就不多谈了。

  再回到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”这段代码了。

Django Rest Framework之版本控制的更多相关文章

  1. Django REST framework - 版本控制

    目录 Django REST framework 版本控制 为什么需要版本控制 DRF提供了5种版本控制方案 版本控制系统的使用 全局配置 局部配置 获取版本信息 Django REST framew ...

  2. Django REST framework反向生成url

    Django REST framework是一个基于Django的框架,REST framework又是怎么反向生成url的呢?? 在前面的例子中,知道在REST framework中有6种版本控制的 ...

  3. django rest framework restful 规范

    内容回顾: . django请求生命周期 -> 执行遵循wsgi协议的模块(socket服务端) -> 中间件(路由匹配) -> 视图函数(业务处理:ORM.模板渲染) -> ...

  4. Django Rest Framework源码剖析(四)-----API版本

    一.简介 在我们给外部提供的API中,可会存在多个版本,不同的版本可能对应的功能不同,所以这时候版本使用就显得尤为重要,django rest framework也为我们提供了多种版本使用方法. 二. ...

  5. Django Rest FrameWork 全部API

    Django Rest FrameWork .Requests 请求 客服端发送给服务器的请求 .Responses 响应 rest框架支持响应不同格式的内容 .Views 视图 base基础类视图 ...

  6. Django REST Framework 学习笔记

    前言: 基于一些不错的RESTful开发组件,可以快速的开发出不错的RESTful API,但如果不了解开发规范的.健壮的RESTful API的基本面,即便优秀的RESTful开发组件摆在面前,也无 ...

  7. DRF Django REST framework APIView(一)

    什么是REST? REST是一个标准,一种规范,遵循REST风格可以使开发的接口通用,便于调用者理解接口的作用. 使url更容易理解,让增删改清晰易懂,在前后端分离开发中按照这一规范能加快开发效率,减 ...

  8. django restful framework教程大全

    一. 什么是RESTful REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角 ...

  9. Django Rest Framework API指南

    Django Rest Framework API指南 Django Rest Framework 所有API如下: Request 请求 Response 响应 View 视图 Generic vi ...

随机推荐

  1. Hadoop 系列文章(二) Hadoop配置部署启动HDFS及本地模式运行MapReduce

    接着上一篇文章,继续我们 hadoop 的入门案例. 1. 修改 core-site.xml 文件 [bamboo@hadoop-senior hadoop-2.5.0]$ vim etc/hadoo ...

  2. 编译与解释(java)

    计算机不能直接理解高级语言,只能直接理解机器语言,所以必须要把高级语言翻译成机器语言,计算机才能执行高级语言编写的程序. 翻译的方式有两种,一个是编译,一个是解释.两种方式只是翻译的时间不同 计算机不 ...

  3. We FALL ASleep At Night, We Do REST Right

    We Do Sleep At Night, We Do REST Right 前言 REST 起源 REST 约束 客户端 - 服务端 无状态 缓存 统一接口 分层系统 按需代码 统一接口约束 资源识 ...

  4. NET Core微服务之路:实战SkyWalking+Exceptionless体验生产环境下的追踪系统

    前言 当一个APM或一个日志中心实际部署在生产环境中时,是有点力不从心的. 比如如下场景分析的问题: 从APM上说,知道某个节点出现异常,或延迟过过高,却不能及时知道日志反馈情况,总不可能去相应的节点 ...

  5. Android NDK学习(三):Hello World

    版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/6925810.html 首先编写Jni接口的c文件,此文件命名有些特殊,具体的命名方式可以参考文档来做. # ...

  6. MySQL数值类型

    MySQL数值类型 MySQL支持所有标准的SQL数值数据类型.这些类型包括数值数据类型INTEGER.SMALLINT.DECIMAL.NUMERIC和近似数值数据类型FLOAT.REAL.DOUB ...

  7. LeetCode:151_Reverse Words in a String | 字符串中单词的逆反 | Medium

    题目:Reverse Words in a String Given an input string, reverse the string word by word. For example, Gi ...

  8. eclipse clean和build作用

    由于eclipse的编译是基于时间戳的判断机制的. 因此当你按build   all的时候有些eclipse认为时间戳没有改变的类不会被编译. 因此你可以先clean一下再编译.这个时候eclipse ...

  9. 为什么我们喜欢用 sigmoid 这类 S 型非线性变换?

    本文整理自 @老师木 的一条图片新浪微博,从另一个角度给出为何采用 sigmoid 函数作非线性变换的解释. 为什么我们喜欢用 sigmoid 这类 S 型非线性变换?

  10. python常用函数和方法 - 备忘

    语法语句篇 除法运算(精确运算和截断运算) 在python2中,除法运算通常是截断除法.什么是截断除法: >>> 3/4 0 # 自动忽略小数项 要是想 得到正确结果 怎么办呢? m ...