路由组件

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

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. jQuery随笔记录

            DOM遍历 parent()方法返回所选元素的直接父元素.(parent() 只能遍历单个级别的 DOM树) parents()方法获取所选元素的所有祖先 children()所选元素 ...

  2. 设置UICollectionViewCell圆角和阴影

    设置cell圆角: cell.contentView.layer.cornerRadius =2.0f; cell.contentView.layer.borderWidth =1.0f; cell. ...

  3. Mysql安装、配置、优化

    MYSQL定义 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle旗下产品.MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最 ...

  4. 基于django的个人博客网站建立(五)

    基于django的个人博客网站建立(五) 前言 网站效果可点击这里访问 之前鸽了两天,今天继续再写点 主要内容 今天加了个展示照片的功能,就叫他生活记录吧 先建表 class Record(model ...

  5. 《Web Development with Go》Mangodb插入map,slice,Embedded Documents

    这几个好理解, 更好的实现,再说. package main import ( "fmt" "log" "time" "gopkg ...

  6. 使用admin的步骤、必知必会13条、单表的双下划线、外键的操作、多对多的操作:

    MVC M: model 模型 与数据库交互 V: view 视图 HTML C:controller 控制器 流程 和 业务逻辑 MTV M:model ORM T:template 模板 HTML ...

  7. FFT/NTT中档题总结

    被DeepinC%怕了,把一些题放到这里来 T1Normal 其实这道题放到中档题也不太合适,个人感觉真的很难,机房里好像都是颓的题解 因为期望的可加性,把每个点的贡献单独处理,即求期望深度 考虑$y ...

  8. [译]Vulkan教程(01)入门

    [译]Vulkan教程(01)入门 接下来我将翻译(https://vulkan-tutorial.com)上的Vulkan教程.这可能是我学习Vulkan的最好方式,但不是最理想的方式. 我会用“d ...

  9. 浅谈Kotlin中的函数

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/UV23Uw_969oVhiOdo4ZKAw作者:连凌能 Kotlin,已经被Android官方 ...

  10. Python中的常见特殊方法—— repr方法

    在Python中有些方法名.属性名的前后都添加了双下划线,这种方法.属性通常都属于Python的特殊方法和特殊属性,开发者可以通过重写这些方法或者直接调用这些方法来实现特殊的功能.其实前面见过的构造方 ...