基本代码结构

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. 为opencv添加contrib库

    自从进入3.X时代以后,OpenCV将代码库分成了两部分,分别是稳定的核心功能库和试验性质的contrib库,之前已经讲过opencv的核心库的安装,现在讲解一下其附带的依赖库的安装. 一.Cmake ...

  2. hdu3001Travelling

    参考了别人的代码   https://blog.csdn.net/u010372095/article/details/38474721 深感自己的弱小 这是tsp问题,和基本的tsp问题没什么大的区 ...

  3. 深度学习框架caffe/CNTK/Tensorflow/Theano/Torch的对比

    在单GPU下,所有这些工具集都调用cuDNN,因此只要外层的计算或者内存分配差异不大其性能表现都差不多. Caffe: 1)主流工业级深度学习工具,具有出色的卷积神经网络实现.在计算机视觉领域Caff ...

  4. Avoiding Common Networking Mistakes

    https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/Networkin ...

  5. Java学习笔记45(多线程二:安全问题以及解决原理)

    线程安全问题以及解决原理: 多个线程用一个共享数据时候出现安全问题 一个经典案例: 电影院卖票,共有100座位,最多卖100张票,买票方式有多种,网上购买.自主售票机.排队购买 三种方式操作同一个共享 ...

  6. Python - 集成开发环境Pycharm的使用方法和技巧

    PyCharm HomePage:PyCharm 我的Pycharm,我做主 Getting Started with PyCharm Pycharm使用技巧 Documentation & ...

  7. Shell - Shell脚本调试方法

    Shell脚本调试选项 Shell本身提供一些调试方法选项: -n,读一遍脚本中的命令但不执行,用于检查脚本中的语法错误. -v,一边执行脚本,一边将执行过的脚本命令打印到标准输出. -x,提供跟踪执 ...

  8. java main()线程是不是最后一个退出的(相比较main中创建的其他多个线程)

    JVM会在所有的非守护线程(用户线程)执行完毕后退出: main线程是用户线程: 仅有main线程一个用户线程执行完毕,不能决定JVM是否退出,也即是说main线程并不一定是最后一个退出的线程. pu ...

  9. Java异常处理设计(三)

    接着上一篇讲. 一个异常日志处理的例子: 抛出异常的地方为: try{ ... ...//省略N行 }catch( Exception e){ throw new RuntimeException ( ...

  10. 使用 Portainer UI 管理 Docker 主机

    Docker 使用命令行的方式来管理有时候并没有那么直观,可以使用 Portainer 的 UI 来管理 Docker 主机和 Docker Swarm 集群. 安装 Portainer 环境:cen ...