一、前言

1、版本的重要性

RESTful 规范中,有关版本的问题,用restful规范做开放接口的时候,用户请求API,系统返回数据。但是难免在系统发展的过程中,不可避免的需要添加新的资源,或者修改现有资源。因此,改动升级必不可少,但是,作为平台开发者,应该知道:一旦你的API开放出去,有人开始用了,平台的任何改动都需要考虑对当前用户的影响。因此,做开放平台,从第一个API的设计就需要开始API的版本控制策略问题,API的版本控制策略就像是开放平台和平台用户之间的长期协议,其设计的好坏将直接决定用户是否使用该平台,或者说用户在使用之后是否会因为某次版本升级直接弃用该平台。

2、定义版本

怎么定义版本协议,前端后端怎么协调。有以下几种方式:

  • 请求头中定义
    GET /something/ HTTP/1.1
Host: example.com
Accept: application/json; version=1.0 #版本为1.0
  • URL中定义
    URL: example.com/v1.0/  # 版本为1.0
GET /1.0/something/ HTTP/1.1
Host: example.com
Accept: application/json
  • 子域名中定义
    GET /something/ HTTP/1.1
Host: v1.example.com # 版本为1.0
Accept: application/json
  • HttpReqeust参数传递
    GET /something/?version=0.1 HTTP/1.1  # 版本为1.0
Host: example.com
Accept: application/json

二、示例

django rest framewrok中,如果没有在配置文件setting.py中设置默认的VERSION_PARAM,即版本参数,drf会设置默认的参数为version,并将获取到的version的值封装到request.version

1、请求头中定义

django rest frameworkrequest其实是对原生的DjangoHttpRequest做了一个封装,通过直接获取属性可以获取到请求头中的版本号

django rest framework的request

原生的DjangoHttpRequest

请求头的版本和其他请求头信息最终会放到META中,因此想要获取版本号可以如下这样

version = request._request.META.get('version')  # 获取版本号

2、子域名中定义

同样的像请求头中定义一样,在请求头中也可以直接获取的域名,放到META中,因此想要获取版本号可以如下这样

host = request._request.META.get('HTTP_HOST')  # 先获取主机域名
version = host.split('.')[0] # 获取版本号

注:其实在django rest framework内部也有关于以上两种定义版本的处理方法

3、HttpReqeust参数传递

之前分别在django rest framework中关于节流,认证,权限三个组件,这里新建一个Django项目,命名为drf2。并进入当前目录下执行python manage.py startapp api,将新建的app,和rest_framework放入INSTALLED_APPS。

# setting.py

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'api'
]

<1>、目录结构

<2>、路由系统

from django.conf.urls import url

from .views import VersionView

urlpatterns = [
url(r'^version/$', VersionView.as_view()), ]

<3>、视图

from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework.versioning import QueryParameterVersioning class VersionView(APIView):
versioning_class = QueryParameterVersioning # 局部配置请求参数处理 def get(self, request, *args, **kwargs):
version = request.version
ret = {
'code': 1000,
'msg': '请求成功',
‘version': version
}
return JsonResponse(ret)

<4>、配置文件

像之前在权限,节流那样,可以配置一个全局默认的版本解析类

REST_FRAMEWORK = {
"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning", # 默认是url处理版本
"DEFAULT_VERSION":'v1', # 默认版本
"ALLOWED_VERSIONS":['v1','v2'], # 允许版本
"VERSION_PARAM":'version', # 版本参数例如 ?version=v1,,则表示版本为v1
}

<5>、测试

使用postman或者浏览器发送请求测试

提供正常版本号http://127.0.0.1:8000/api/version/?version=v1 获取版本成功

发送错误版本号http://127.0.0.1:8000/api/version/?version=v3 由于允许版本只有v1和v2,所以版本错误,返回错误信息

不提供版本号:假如在url请求中不添加参数,http://127.0.0.1:8000/api/version/?,能获取到默认的版本号

4、URL中定义

在url中定义,例如http://127.0.0.1:8000/api/v1/

<1>、路由系统

from django.conf.urls import url

from .views import VersionView

urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/$', VersionView.as_view()), # 可用版本为v1和v2
]

<2>、视图

from django.http import JsonResponse
from django.http import HttpRequest
from rest_framework.views import APIView, Request
from rest_framework.versioning import URLPathVersioning class VersionView(APIView):
versioning_class = URLPathVersioning # 局部配置版本类 def get(self, request, *args, **kwargs):
version = request.version
ret = {
'code': 1000,
'msg': '请求成功',
'version': version
}
return JsonResponse(ret)

或者也可以全局配置, 不过使用URL解析的时候,需要在路由系统中正则匹配设置可用的版本,

REST_FRAMEWORK = {
"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning",
"VERSION_PARAM":'version', # 参数
}

<3>、测试

使用postman或者浏览器发送请求测试

http://127.0.0.1:8000/api/v1/,正确的获取版本号

5、反向解析URL

在django中也提供了一个url解析的函数reverse,不过在django rest framework中也有一个将reverse函数封装一层的接口可以进行url反向解析。

路由系统:加入namespace参数

from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url urlpatterns = [
url(r'^api/', include('api.urls', namespace='api') ),
]

子路由系统:加入name参数

from django.conf.urls import url

from .views import VersionView

app_name = 'api' 

urlpatterns = [
url(r'^version/$', VersionView.as_view(), name='version'),
url(r'^(?P<version>[v1|v2]+)/$', VersionView.as_view(), name='version'),
]

示例一:参数携带版本

http://127.0.0.1:8000/api/version/?version=v1,发送请求

class VersionView(APIView):
versioning_class = QueryParameterVersioning def get(self, request, *args, **kwargs): version = request.version
url1 = request.versioning_scheme.reverse(viewname='api:version', request=request) url2 = reverse(viewname='api:version', kwargs=kwargs) ret = {
'code': 1000,
'msg': '请求成功',
'version': version,
'drf_url': url1,
'django_url': url2
}
return JsonResponse(ret)

使用postman返送请求

示例二:URL携带版本

http://127.0.0.1:8000/api/v1/,发送请求

class VersionView(APIView):
versioning_class = URLPathVersioning def get(self, request, *args, **kwargs): version = request.version
url1 = request.versioning_scheme.reverse(viewname='api:version', request=request) url2 = reverse(viewname='api:version', kwargs=kwargs) ret = {
'code': 1000,
'msg': '请求成功',
'version': version,
'drf_url': url1,
'django_url': url2
}
return JsonResponse(ret)

使用postman返送请求

这里有与drf的reverse在对django中的reverse函数进行封装的时候,获取了request.get_full_url(),并做了一个拼接,所以才会出现全部的url

三、源码分析

1、找到initial()方法

依旧从dispath方法进入源码,找到initial方法

2、进入initial()方法

这里调用了determine_version()方法,并拿到两个返回值并封装到request中。这时候request.version_scheme就是一个版本对象了

3、查看具体的determine_version()方法

4、默认的版本处理对象

可以在setting.py中配置之后,全局使用

5、drf提供的版本类

在url反向解析中,调用了request.versioning_scheme.reverse()中的reverse()方法,说明request.versioning_scheme返回的是一个版本对象,可以调用他的方法

BaseVersioning基类定义了三个接口

  • determine_version:返回版本
  • reverse:url反向解析使用
  • is_allowed_version:就是判断版本号是否合法

而上面示例使用的两个超类URLPathVersioning,QueryParameterVersioning其实也就是,重写了determine_version,和reverse两个方法。

四、总结

版本的获取方式有多种,在django rest framewok中也提供了一一对应的处理版本对象,可以根据自己的需要配置,或者继承重写接口使用。

配置也支持全局配置,和局部配置,在全局配置的时候,需要定义默认的版本号,以防万一。

在进行url反向解析的时候django rest framewok提供了一个更好的方式。

Django Rest framework 之 版本的更多相关文章

  1. Django REST framework之版本,解释器,序列化

    1 版本 2 解释器 3.序列化 1 版本 通过?后面传版本号有两种方法: 方法一 from django.shortcuts import render from rest_framework.vi ...

  2. Django rest framework 之版本

    一.通过 QueryParameterVersioning 获取版本 通过 QueryParameterVersioning 从 get 请求中获取版本信息: 1.新建 app,名为 api,Proj ...

  3. Django Rest framework 之 序列化

    RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...

  4. Django Rest framework 之 解析器

    RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...

  5. Django Rest framework 之 节流

    RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...

  6. Django Rest framework 之 权限

    django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) django res ...

  7. Django Rest framework 之 认证

    django rest framework 官网 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest fra ...

  8. Django Rest framework 之 视图

    RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...

  9. Django Rest framework 之 分页

    RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...

随机推荐

  1. 你应该这么理解TCP的三次握手和四次挥手

    前言: TCP协议是计算机的基础,他本身是一个非常非常复杂的协议. 本文只是蜻蜓点水,将从网络基础以及TCP的相关概念介绍开始,之后再将三次握手,四次挥手这些内容来阐述. 最后介绍一些常见问题,并给出 ...

  2. dtb和dtc文件浅析

    目录 dtb和dtc文件浅析 工具集 dts格式 dtb头部结构 dtb标识符 分析具体的文件 title: dtb和dtc文件浅析 date: 2019/4/25 20:09:38 toc: tru ...

  3. 漏洞应急响应之批量poc验证

    1.文章难易度 [★★★] 2.文章知识点: python,poc验证; 3.文章作者: 野驴 4.本文参与 i春秋学院原创文章奖励计划,未经许可禁止转载! 0x01前言 当互联网爆出高危漏洞,或者团 ...

  4. 如何设置 sass 全局变量,js如何使用 sass 变量

    关键词:sass全局变量 js引用sass变量 1 如何在样式中使用 scss 的声明的全局变量 假设我们有一个全局的 scss 变量文件/styles/_vars.sass,如下: $red: re ...

  5. celery异步认知

    celery是异步任务的框架 是由python实现的异步框架. 在使用celery我们经常分为三个部分, 第一部分就是我们所说的客户端, 就是发起异步任务的一方, 第二部分 任务队列 broker 第 ...

  6. MySQL:索引

    索引的目的在于提高查询效率,它的作用就相当于一本书的目录: 1. 常见的索引模型 1.1 哈希表 优点:适用于等值查询的场景: 缺点:范围查询效率较低: 1.2 有序数组 优点:范围查询和等值查询效率 ...

  7. 使用node.js + json-server + mock.js 搭建本地开发mock数据服务

    在开发过程中,前后端不论是否分离,接口多半是滞后于页面开发的.所以建立一个REST风格的API接口,给前端页面提供虚拟的数据,是非常有必要的.对比过多种mock工具后,我最终选择了使用 json se ...

  8. Spring Boot Starters启动器

    Starters是什么? Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成Spring及其他技术,而不需要到处找示例代码和依赖包.如你想使用Spring J ...

  9. Ehcache3开发入门简介

    在高并发应用中缓存就是核心机制.最近在研究Ehcache,发现这是一个更加灵活易用的缓存框架(相对于Redis.Memcache),Ehcache更加小巧轻便.而且都有持久化机制,不用担心JVM和服务 ...

  10. kafka+elk

    安装elasticsearch 下载:http://www.elastic.co/downloads/elasticsearch 下载后解压 修改配置文件,xxx是自定义目录 vi elasticse ...