13.DRF-版本
Django rest framework源码分析(4)----版本
版本
新建一个工程Myproject和一个app名为api
(1)api/models.py
from django.db import models
class UserInfo(models.Model):
USER_TYPE = (
(1,'普通用户'),
(2,'VIP'),
(3,'SVIP')
)
user_type = models.IntegerField(choices=USER_TYPE)
username = models.CharField(max_length=32,unique=True)
password = models.CharField(max_length=64)
group = models.ForeignKey('UserGroup',on_delete=models.CASCADE)
roles = models.ManyToManyField('Role')
class UserToken(models.Model):
user = models.OneToOneField('UserInfo',on_delete=models.CASCADE)
token = models.CharField(max_length=64)
class UserGroup(models.Model):
title = models.CharField(max_length=32)
class Role(models.Model):
title = models.CharField(max_length=32)
(2)Myproject/urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
#path('admin/', admin.site.urls),
path('api/',include('api.urls') ),
]
(3)api/urls.py
# api/urls.py
from django.urls import path
from .views import UserView
urlpatterns = [
path('users/', UserView.as_view()),
]
(4)views.py
# api/views.py
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.versioning import QueryParameterVersioning
class UserView(APIView):
versioning_class = QueryParameterVersioning
def get(self,request,*args,**kwargs):
#获取版本
print(request.version)
return HttpResponse('用户列表')
(5)settings.py
#版本
REST_FRAMEWORK = {
"DEFAULT_VERSION":'v1', #默认的版本
"ALLOWED_VERSIONS":['v1','v2'], #允许的版本
"VERSION_PARAM":'version' #GET方式url中参数的名字 ?version=xxx
}
1.url中通过GET传参
QueryParameterVersioning用于去GET参数中取version
http://127.0.0.1:8000/api/users/?version=v2
后台可以看到当前的版本

如果url中没有传版本参数,则显示默认的版本("DEFAULT_VERSION":'v1')
http://127.0.0.1:8000/api/users/

如果url传的版本超过settings中的允许范围则报错
http://127.0.0.1:8000/api/users/?version=v3

2.在URLPATH中获取
(1)修改api/urls.py
通常情况我门应该用URLPATH的方式,而不是用前面GET()传参方式
url里面通过正则表达式定义哪些版本,
# api/urls.py
from django.urls import path,re_path
from .views import UserView
urlpatterns = [
re_path('(?P<version>[v1|v2]+)/users/', UserView.as_view()),
]
(2)views.py
URLPathVersioning:去url路径里面获取版本
# api/views.py
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.versioning import URLPathVersioning
class UserView(APIView):
versioning_class = URLPathVersioning
def get(self,request,*args,**kwargs):
#获取版本
print(request.version)
return HttpResponse('用户列表')
这个URLPathVersioning我们可以放到settings里面,全局配置,就不用写到views里面,每个类都要写一遍了
settings.py
# 版本
# REST_FRAMEWORK = {
# "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
# "DEFAULT_VERSION":'v1', #默认的版本
# "ALLOWED_VERSIONS":['v1','v2'], #允许的版本
# "VERSION_PARAM":'version' #get方式url中参数的名字 ?version=xxx
# }
#全局
REST_FRAMEWORK = {
"DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
}
修改views.py
# api/views.py
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.request import Request
class UserView(APIView):
def get(self,request,*args,**kwargs):
#获取版本
print(request.version)
return HttpResponse('用户列表')
浏览器访问地址
http://127.0.0.1:8000/api/v1/users/
然后后台拿到版本信息
3.反向解析访问的url
(1)api/urls.py
添加name = 'api_user'
# api/urls.py
from django.urls import path,re_path
from .views import UserView
urlpatterns = [
re_path('(?P<version>[v1|v2]+)/users/', UserView.as_view(),name = 'api_user'),
]
(2)views.py
# api/views.py
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.request import Request
class UserView(APIView):
def get(self,request,*args,**kwargs):
#获取版本
print(request.version)
#获取处理版本的对象
print(request.versioning_scheme)
#获取浏览器访问的url,reverse反向解析
#需要两个参数:viewname就是url中的别名,request=request是url中要传入的参数
#(?P<version>[v1|v2]+)/users/,这里本来需要传version的参数,但是version包含在request里面(源码里面可以看到),所有只需要request=request就可以
url_path = request.versioning_scheme.reverse(viewname='api_user',request=request)
print(url_path)
# self.dispatch
return HttpResponse('用户列表')
浏览器访问
http://127.0.0.1:8000/api/v1/users/
后台获取

源码流程
(1)dispatch
def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
#对原始request进行加工,丰富了一些功能
#Request(
# request,
# parsers=self.get_parsers(),
# authenticators=self.get_authenticators(),
# negotiator=self.get_content_negotiator(),
# parser_context=parser_context
# )
#request(原始request,[BasicAuthentications对象,])
#获取原生request,request._request
#获取认证类的对象,request.authticators
#1.封装request
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
#2.认证
self.initial(request, *args, **kwargs)
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
(2)initial
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs)
# Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
# Determine the API version, if versioning is in use.
#request.version获取版本信息
#request.versioning_scheme获取处理版本你的对象
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
# Ensure that the incoming request is permitted
#4.实现认证
self.perform_authentication(request)
#5.权限判断
self.check_permissions(request)
#6.控制访问频率
self.check_throttles(request)
(3)determine_version
def determine_version(self, request, *args, **kwargs):
"""
If versioning is being used, then determine any API version for the
incoming request. Returns a two-tuple of (version, versioning_scheme)
"""
if self.versioning_class is None:
return (None, None)
scheme = self.versioning_class()
return (scheme.determine_version(request, *args, **kwargs), scheme)
(4)versioning_class

URLPathVersioning源码
class URLPathVersioning(BaseVersioning):
"""
To the client this is the same style as `NamespaceVersioning`.
The difference is in the backend - this implementation uses
Django'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.1
Host: example.com
Accept: 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 not self.is_allowed_version(version):
raise exceptions.NotFound(self.invalid_version_message)
return version
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
if request.version is not None:
kwargs = {} if (kwargs is None) else kwargs
kwargs[self.version_param] = request.version
return super(URLPathVersioning, self).reverse(
viewname, args, kwargs, request, format, **extra
)
可以看到
(1)url配置

(2)determine_version
里面有个is_allowed_version,点进去可以看到一些基本参数 (继承BaseVersioning基类)
class BaseVersioning(object):
#默认的版本
default_version = api_settings.DEFAULT_VERSION
#允许的版本
allowed_versions = api_settings.ALLOWED_VERSIONS
#默认参数(是version,比如你可以自定义为v)
version_param = api_settings.VERSION_PARAM
def 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 True
return ((version is not None and version == self.default_version) or
(version in self.allowed_versions))
13.DRF-版本的更多相关文章
- python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)
昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...
- 黑苹果之DELL台式机安装Mac OS X 10.13.6版本操作系统
由于本人所在的公司一般都是DELL的品牌台式机,所以以DELL台式机做小白鼠.记得在2012年的时候,在当时的那家公司为了学习自学IOS开发的Objective-C开发语言的时候,由于囊中羞涩买不起m ...
- 金蝶K3 WISE 13.1版本服务器虚拟机环境部署
闲来无事,整个13.1版本的金蝶玩玩. 系统环境:WIN2008 R2,x64位 数据库:MSSQL 2008 R2,X64位 记录下操作步骤: 1.准备安装软件,见图: 2.安装资源包,.net3. ...
- DRF版本组件
1.DRF版本组件配置类局部使用 局部配置: 方式一:直接配置versioning_class=QueryParameterVersioning 方式二:直接配置versioning_class=UR ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》- 13.中英文版本切换设计
目 录 第十三章 中英文版本切换设计... 2 13.1 不用自带的资源文件的理由... 2 13.2 配置文件... 2 13.3 语言 ...
- DRF 版本 认证
DRF的版本 版本控制是做什么用的, 我们为什么要用 首先我们要知道我们的版本是干嘛用的呢大家都知道我们开发项目是有多个版本的 当我们项目越来越更新~版本就越来越多我们不可能新的版本出了~以前旧的版本 ...
- DRF 版本和认证
Django Rest Framework 版本控制组件 DRF的版本 版本控制是做什么用的, 我们为什么要用 首先我们要知道我们的版本是干嘛用的呢~~大家都知道我们开发项目是有多个版本的~~ 当我们 ...
- DRF 版本 及认证
版本控制 -- # 初始化我们的版本 version, scheme = self.determine_version(request, *args, **kwargs) request.v ...
- 【DRF版本】
目录 使用内置的URLPathVersioning类 使用自定义的版本控制类 首先,我们开发的项目会有多个版本. 其次,我们的项目版本会随着更新越来越多,我们不可能因出了新版本就不维护旧版本了. 那么 ...
- DRF 版本、认证、权限、限制、解析器和渲染器
目录 一.DRF之版本控制 为什么要有版本控制? DRF提供的版本控制方案 版本的使用 全局配置 局部配置(使用较少) 二.DRF之认证 内置的认证 步骤 三.DRF之权限 1.自定义一个权限类 2. ...
随机推荐
- 最小生成树——Kruskal算法理解
背景:本文是在小甲鱼数据结构教学视频中的代码的基础上,添加详细注释而完成的.该段代码并不完整,仅摘录了核心算法部分,结合自己的思考,谈谈理解. Prim算法理解: 如图(摘录自小甲鱼教学视频中的图片) ...
- Verilog - ABS代码重构
https://mp.weixin.qq.com/s/-KUviTzO3Hdir_mI57L24g 从形式和语义两个层面,来扣一下ABS这段代码. 目的在于:在不降低通用性.不增加复杂度的情况下,提升 ...
- ssm中的依赖配置
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-conte ...
- Java实现 LeetCode 539 最小时间差(单位转换)
539. 最小时间差 给定一个 24 小时制(小时:分钟)的时间列表,找出列表中任意两个时间的最小时间差并已分钟数表示. 示例 1: 输入: ["23:59","00:0 ...
- Java实现 LeetCode 509 斐波那契数
509. 斐波那契数 斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列.该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和.也就是: F(0) = 0, F(1) = 1 ...
- Java实现 LeetCode 479 最大回文数乘积
479. 最大回文数乘积 你需要找到由两个 n 位数的乘积组成的最大回文数. 由于结果会很大,你只需返回最大回文数 mod 1337得到的结果. 示例: 输入: 2 输出: 987 解释: 99 x ...
- Java实现 蓝桥杯 历届试题 核桃的数量
历届试题 核桃的数量 时间限制:1.0s 内存限制:256.0MB 问题描述 小张是软件项目经理,他带领3个开发组.工期紧,今天都在加班呢.为鼓舞士气,小张打算给每个组发一袋核桃(据传言能补脑).他的 ...
- Arrays.binarySearch和Collections.binarySearch的详细用法
概述 binarysearch为在指定数组中查找指定值得索引值,该值在范围内找得到则返回该值的索引值,找不到则返回该值的插入位置,如果该值大于指定范围最大值则返回-(maxlength+1),而: i ...
- java实现公式解析
在某些应用中,为了支持灵活性,往往用到自定义的公式. 比如,有如下的原始公式集合: int add(int x, int y): 返回x与y的和 int add(int x, int y, int z ...
- java实现人员排日程
某保密单位机要人员 A,B,C,D,E 每周需要工作5天,休息2天. 上级要求每个人每周的工作日和休息日安排必须是固定的,不能在周间变更. 此外,由于工作需要,还有如下要求: 所有人的连续工作日不能多 ...