路由组件

先来看下我们前面写的路由

from django.conf.urls import url, include
from .views import BookModelView urlpatterns = [
url(r'^book/$', BookModelView.as_view({"get": "list", "post": "create"})),
url(r'^book/(?P<pk>\d+)', BookModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
]

这样写路由也没有什么问题,DRF也提供给了我们另一种写法

from .views import  BookModelView
# 帮助我们生成带参数的路由
from rest_framework.routers import DefaultRouter # 实例化DefaultRouter对象
router = DefaultRouter() # 注册我们的路由以及视图
router.register(r'^book', BookModelView) urlpatterns = [ ] # 把我们注册的路由添加到里面
urlpatterns += router.urls

我们在浏览器里输入错误的地址看DRF都给我们生成了哪些路由

^api/ ^^book/$ [name='book-list']
^api/ ^^book\.(?P<format>[a-z0-9]+)/?$ [name='book-list']
^api/ ^^book/(?P<pk>[^/.]+)/$ [name='book-detail']
^api/ ^^book/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='book-detail']
^api/ ^$ [name='api-root']
^api/ ^\.(?P<format>[a-z0-9]+)/?$ [name='api-root']

这种注册路由得方法在实际项目中并不常用,因为把这些路由都开放,会造成一定的安全性

版本控制

我们的网站要在不同的阶段加入不同的功能,restful规定了我们的接口要有版本号。但是不是所有人看到有更新就会更新的,所以我们的要兼容不同的版本。而前端肯定能拿到用户访问的是哪个版本的,这样,让前端的妹子把版本号传给后端,后端拿到版本号,做不同的处理,在把结果返回给前端就可以了。

既然我们知道了前端妹子可以拿到版本号,那怎么传给后端,是放在url里还是放在header里,或者是请求体里。这些都可以,妹子怎么高兴怎么来。

我们先来分析一下DRF里的源码是怎么写的

进入APIView类里,找到dispatch方法,找到下面的代码

try:
self.initial(request, *args, **kwargs)

进入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.
# 初始化我们的版本
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted
# 认证组件
self.perform_authentication(request)
# 权限组件
self.check_permissions(request)
# 频率
self.check_throttles(request)

源码里会把 determine_version方法的结果解包赋值给version,然后把version赋值给了request.version去看看 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)

里面判断了versioning_class这个方法的返回值是不是None,默认api_settings里的DEFAULTS里的DEFAULT_VERSIONING_CLASS'为None,所以版本默认就是为None,我们可以写个方法来测试一下

class VersionDemo(APIView):
def get(self, request):
print(request.version)
print(request.versioning_scheme)
return Response("ok")

最后的结果就是None

所以我们可以重写DEFAULT_VERSIONING_CLASS这个方法。哪我们在哪里重写呢?Django给我们提供了settings.py文件,这里面的会覆盖默认的配置。好了,既然我们已经知道了在哪里重写,那我们就来实践一遍

全局版本类的配置

先在项目的根目录下创建个utils文件夹,在创建个version.py文件

在里面写如下代码

class MyVersion(object):
def determine_version(self, request, *args, **kwargs): # 必须是这个函数名
# 方法的返回值是版本号
# 获取前端传过来的版本号,并且把版本号返回
version = request.query_params.get('version') # 前端在url里携带版本号
if not version:
version = 'v1'
return version

写好了去settings.py里配置

REST_FRAMEWORK = {
"DEFAULT_VERSIONING_CLASS":"utils.version.MyVersion"
} # utils.version.MyVersion 文件里的类名

然后访问类似这样的地址:http://127.0.0.1:8000/version/demo/?version=v3,控制台打印出的就是v3。既然我们能拿到版本号了,那我们就能根据版本号做不同的逻辑处理了。修改views下的VersionDemo类

class VersionDemo(APIView):
def get(self, request):
print(request.version)
print(request.versioning_scheme)
# 根据版本号处理不同的业务逻辑
if request.version == 'v2':
return Response('这是v2的业务逻辑')
return Response("这是v1的业务逻辑")

上面的配置是全局的配置,假如我们现在有两个类

from rest_framework.views import APIView
from rest_framework.response import Response class VersionDemo(APIView):   def get(self, request):
print(request.version)
print(request.versioning_scheme)
# 根据版本号处理不同的业务逻辑
if request.version == 'v2':
return Response('这是v2的业务逻辑')
return Response("这是v1的业务逻辑") class VersionTest(APIView):
def get(self, request):
print(request.version)
print(request.versioning_scheme)
# 根据版本号处理不同的业务逻辑
if request.version == 'v2':
return Response('这是v3的业务逻辑')
return Response("这是v4的业务逻辑")

现在不管访问哪个类都会走我们定义的MyVersion类,有时候,我们只希望一部分类有版本控制,一部分不需要版本控制。DRF可以允许我们局部配置

局部配置版本号

局部配置版本号要先注释掉settings.py里写的配置项

# REST_FRAMEWORK = {
# "DEFAULT_VERSIONING_CLASS":"utils.version.MyVersion"
# }

然后在需要版本控制的方法前加上 versioning_class=版本类,类似于下面这样

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from utils.version import MyVersion class VersionDemo(APIView):
versioning_class = MyVersion def get(self, request):
print(request.version)
print(request.versioning_scheme)
# 根据版本号处理不同的业务逻辑
if request.version == 'v2':
return Response('这是v2的业务逻辑')
return Response("这是v1的业务逻辑") class VersionTest(APIView):
def get(self, request):
print(request.version)
print(request.versioning_scheme)
# 根据版本号处理不同的业务逻辑
if request.version == 'v2':
return Response('这是v3的业务逻辑')
return Response("这是v4的业务逻辑")

这样配置好了之后,我们访问 VersionDemo,就会走我们自定义的版本类。如果访问 VersionTest,就不会走我们自定义的版本类,版本号为默认的None

使用原始的版本配置类

DRF已经替我们封装好了版本控制类,包括请求头的,url里的,主机里的。。。我们只需要使用就可以了,所有的类都在 versioning 方法里

from rest_framework import versioning

使用局部的时候只需要加上versioning_class就可以了,类似于下面这样

class VersionTest(APIView):
versioning_class = versioning.QueryParameterVersioning # 使用自带的配置
def get(self, request):
print(request.version)
print(request.versioning_scheme)
# 根据版本号处理不同的业务逻辑
if request.version == 'v2':
return Response('这是v3的业务逻辑')
return Response("这是v4的业务逻辑")

如果要使用全局的配置,就需要在settings.py里进行配置了

REST_FRAMEWORK = {
"DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.QueryParameterVersioning"
}

这样就不需要我们自己写版本控制类了

其他的一些配置

REST_FRAMEWORK = {
# 默认使用的版本控制类
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
# 允许的版本
'ALLOWED_VERSIONS': ['v1', 'v2'],
# 版本使用的参数名称
'VERSION_PARAM': 'version',
# 默认使用的版本
'DEFAULT_VERSION': 'v1',
}

DRF--路由组件和版本控制的更多相关文章

  1. drf路由组件(4星)

    路由组件(4星) 路由Routers 对于视图集ViewSet, 我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息. REST f ...

  2. DRF路由组件和渲染器组件

    参考博客:https://www.cnblogs.com/wupeiqi/articles/7805382.html

  3. DRF 视图组件,路由组件

    视图组件  -- 第一次封装   -- GenericAPIView(APIView):    queryset = None    serializer_class = None    def ge ...

  4. 【DRF框架】路由组件

    视图组件涉及的路由补充: from rest_framework.viewsets import ViewSetMixin 对路由进行了重新的分发,重写了as_view() 方法,重新封装了请求方法 ...

  5. drf二次封装response-APIViews视图家族-视图工具集-工具视图-路由组件

    视图类传递参数给序列化类 (1).在视图类中实例化 序列化对象时,可以设置context内容. (2).在序列化类中的局部钩子.全局钩子.create.update方法中,都可以用self.conte ...

  6. DRF版本组件

    1.DRF版本组件配置类局部使用 局部配置: 方式一:直接配置versioning_class=QueryParameterVersioning 方式二:直接配置versioning_class=UR ...

  7. DRF之Jwt 实现自定义和DRF小组件及django-filter插件的使用

    一.DRF之Jwt 实现自定义 二.DRF(过滤,排序,分页)组件 三.Django-filter插件的使用和自定义 """ 1.drf-jwt手动签发与校验 :只是做t ...

  8. drf认证组件、权限组件、jwt认证、签发、jwt框架使用

    目录 一.注册接口 urls.py views.py serializers.py 二.登录接口 三.用户中心接口(权限校验) urls.py views.py serializers.py 四.图书 ...

  9. 视图家族 & 路由组件

    目录 视图家族 & 路由组件 视图集与路由组件 基于 GenericAPIView 的十大接口 基于 generics 包下工具视图类的六大基础接口 视图集 路由组件:必须配合视图集使用 自定 ...

随机推荐

  1. 一些实用的Django+HTML设置

    一.关于引入变量 1.变量引入方法: {% block 块名称 %} <p>{{变量名}}<p> {% endblock %} 2.引入变量的值中标签是否转义: 不转义: {% ...

  2. 利用 uDig 生成 GeoServer 可用的 SLD 渲染文件

    利用 uDig 生成 GeoServer 可用的 SLD 渲染文件 uDig简介 uDig是一个 open source (EPL and BSD) 桌面应用程序框架,构建在Eclipse RCP和G ...

  3. dpwwn: 1 Vulnhub Walkthrough

    主机层面扫描: ╰─ nmap -p1-65535 -sV -A 10.10.202.130 22/tcp   open  ssh     OpenSSH 7.4 (protocol 2.0) 80/ ...

  4. FlowPortal 6.00c 使用xFormDesigner复制粘贴中文总是乱码

    环境: Windows Server 2016中文版 FlowPortal 6.00C 问题: 使用xFormDesigner 在源码选项卡复制粘贴中文总是乱码. 解决办法: 控制面板---区域--- ...

  5. AWS云EC2(RHEL7)添加网络接口与路由调整

    AWS云EC2(RHEL7)添加网络接口与路由调整 Amazon Linux(类似RHEL6,Centos6) 以及 RHEL7 修改MAC地址的说明 RHEL7 Centos7 添加路由 解决RHE ...

  6. leetcode题解:整数反转

    给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123 输出: 321  示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出 ...

  7. GithubPages+Hexo博客搭建记录

    目录 前言 安装Node.js 安装Git 安装Hexo 查看效果 建立Github Pages 注册Github帐户 建立托管博客的仓库 制作SSH密钥 添加公钥到Github 测试连接 把本地的博 ...

  8. 解决 vscode 中 nuget 插件无法获取包版本的问题

    解决 vscode 中 nuget 插件无法获取包版本的问题 1.问题描述 大概在今年的7月份左右,我忽然发现 NuGet Package Manager 拓展没法正常使用了,只能查询到包: 选完包之 ...

  9. ASP.NET Core 3.0 使用 gRPC无法编译问题

    一.问题 创建了gRPC项目后,编译发现报错: 二.解决 1.检查项目路径是否存在中文 2.检查当前Windows用户目录是否为非英文字符,如果是则必须改为英文 修改方法: https://jingy ...

  10. C#中获取指定路径下特定开头和后缀的所有文件

    场景 指定一个文件路径,获取当前路径下所有文件,并筛选出以指定内容开头和结尾的文件. 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 ...