一、版本控制组件

1、为什么要使用版本控制

首先我们开发项目是有多个版本的
当我们项目越来越更新,版本就越来越多,我们不可能新的版本出了,以前旧的版本就不进行维护了
像bootstrap有2、3、4版本的,每个版本都有它对应的url,https://v2.bootcss.com/ 、 https://v3.bootcss.com/
这就需要我们对版本进行控制,这个DRF也给我们提供了一些封装好的版本控制方法

2、原理

1.
在DRF框架中,它默认帮我们设置了版本信息在request.versionrequest.versioning_scheme中,
只是DRF默认的版本信息是None,我们需要重写一些配置,让request.version携带上我自定义的版本信息
request.versioning_scheme是实现版本控制的类的实例化对象

2.

CBV视图函数都是首先会去执行as_view方法的,as_view会找到路由的分发方法dispatch,在真正分发之前会执行initial方法

3、使用

0. 在哪里取版本信息
我们的版本类必须重写determine_version这个方法,request.version就是拿它的返回值
在视图中就可以使用request.version取到版本信息
1. 新建一个py文件
我建在utils文件夹下的version.py
在version.py下重写一个MyVersion类
注意:必须重写determine_version这个方法,因为request.version就是拿它的返回值
class MyVersion(object):
def determine_version(self,request, *args, **kwargs):
version = request.query_params.get("version", "v1")
return version 2. 去项目的settings配置
# 覆盖DRF原本的配置DEFAULT_VERSIONING_CLASS,让它的值指向我们写的那个类 REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'utils.version.MyVersion'
} 3. 在视图中使用
class VersionView(APIView):
def get(self, request):
print(request.version)
print(request.versioning_scheme)
if request.version == 'v1':
return Response("v1版本")
elif request.version == 'v2':
return Response('v2版本')
return Response('不存在的版本')

4、DRF的versioning模块

1. 在这里模块内给我们配置了各种获取版本的类

2. versioning模块
# 基础类
class BaseVersioning(object):
default_version = api_settings.DEFAULT_VERSION
allowed_versions = api_settings.ALLOWED_VERSIONS
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)) # 在请求头中携带版本信息
class AcceptHeaderVersioning(BaseVersioning):
"""
GET /something/ HTTP/1.1
Host: example.com
Accept: application/json; version=1.0
""" # 在URL中携带版本信息
class URLPathVersioning(BaseVersioning):
'''
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')
]
''' # 在namespace中携带版本信息
class NamespaceVersioning(BaseVersioning):
'''
# users/urls.py
urlpatterns = [
url(r'^/users/$', users_list, name='users-list'),
url(r'^/users/(?P<pk>[0-9]+)/$', users_detail, name='users-detail')
] # urls.py
urlpatterns = [
url(r'^v1/', include('users.urls', namespace='v1')),
url(r'^v2/', include('users.urls', namespace='v2'))
]
''' # 在域名中携带版本信息
class HostNameVersioning(BaseVersioning):
"""
GET /something/ HTTP/1.1
Host: v1.example.com
Accept: application/json
""" # 在参数中携带版本信息
class QueryParameterVersioning(BaseVersioning):
"""
GET /something/?version=0.1 HTTP/1.1
Host: example.com
Accept: application/json
"""

version模块的类


3. 基础类的三个配置
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'utils.version.MyVersion',
# 默认版本
'default_version': 'v1',
# 可用版本
'allowed_versions': ['v1', 'v2'],
# 参数
'version_param': 'version',
}
4. 使用DRF的版本控制
方法一
1. 在utils文件夹下的version.py继承versioning的类 from rest_framework import versioning class MyVersion(versioning.URLPathVersioning):
pass 2. urls.py
urlpatterns = [
# url(r'^version_demo/', views.VersionView.as_view()),
url(r'^(?P<version>[v1|v2]+)/version_demo/', views.VersionView.as_view()),
] 3. settings.py
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'utils.version.MyVersion',
# 默认版本
'default_version': 'v1',
# 可用版本
'allowed_versions': ['v1', 'v2'],
# 参数
'version_param': 'version',
} 4.在视图中使用需要接收参数version
class VersionView(APIView):
def get(self, request, version):
print(request.version)
print(request.versioning_scheme)
if request.version == 'v1':
return Response("v1版本")
elif request.version == 'v2':
return Response('v2版本')
return Response('不存在的版本') 5. 在浏览器中
可以输入:
v1/version_demo/
v2/version_demo/ 方法二
其他步骤基本一样,只是我们在配置的时候直接指定某个类
1. urls.py
urlpatterns = [
# url(r'^version_demo/', views.VersionView.as_view()),
url(r'^(?P<version>[v1|v2]+)/version_demo/', views.VersionView.as_view()),
] 2. settings.py
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning', # 指定URLPathVersioning这个类
# 默认版本
'default_version': 'v1',
# 可用版本
'allowed_versions': ['v1', 'v2'],
# 参数
'version_param': 'version',
}

二、认证

1、为什么要认证

我们可以在网站上登录,然后可以有个人中心,对自己信息就行修改
但是我们每次给服务器发请求,由于Http的无状态,导致我们每次都是新的请求
那么服务端需要对每次来的请求进行认证,看用户是否登录,以及登录用户是谁
那么我们服务器对每个请求进行认证的时候,不可能在每个视图函数中都写认证
一定是把认证逻辑抽离出来,以前我们可能会加装饰器,或者中间件,DRF框架也有它的认证

2、原理

在前端进行登录的时候,用户名和密码输入正确后,后端根据用户名和密码拿到这个用户的一些信息(用户名,性别等),
把这些信息加密后生成一个随机字符串token返回给前端,
前端下次请求再来的时候,带上这个随机字符串,后端根据自己的解密算法再算出来,实现认证。

3、原理图解

4、token认证

0. 在哪里取认证的信息
我们的认证类必须重写authenticate这个方法,返回值是元组
第一个值赋值给了request.user, 第二个赋值给request.auth
在视图中就可以使用request.user和request.auth取到认证的信息 1. models.py
class User(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
# 用UUID字符串存随机字符串
token = models.UUIDField(null=True, blank=True)
CHOICES = ((1, "vip"), (2, "普通用户"), (3, "vvip")) 2. settings配置
# 跟版本一样,覆盖原本的配置,使用自己的配置
REST_FRAMEWORK = {
# 配置认证类
# 这样配是全局,所有路由都要认证
'DEFAULT_AUTHENTICATION_CLASSES':['utils.auth.MyAuth', ]
} 3. utils/auth.py
from rest_framework import authentication
from AuthDemo.models import User
from rest_framework.exceptions import AuthenticationFailed class MyAuth(authentication.BaseAuthentication):
# 必须重写authenticate这个方法,返回值是元组
# 第一个值赋值给了request.user, 第二个赋值给request.auth
def authenticate(self, request):
# 获取前端携带的token,看token是否合法
token = request.query_params.get("token", "")
if not token:
raise AuthenticationFailed("没有携带token")
user_obj = User.objects.filter(token=token).first()
# 返回需要的信息
if user_obj:
return (user_obj, token)
# 验证不通过,抛出异常
raise AuthenticationFailed("token不合法") 4. 视图
# 登录后给用户设置uuid
import uuid
class LoginView(APIView):
def post(self, request):
name = request.data.get("name", "")
pwd = request.data.get("pwd", "")
user_obj = User.objects.filter(name=name, pwd=pwd).first()
if user_obj:
# 登录成功,创建一个token返回给前端
token = uuid.uuid4()
user_obj.token = token
user_obj.save()
return Response(token)
return Response("用户名或密码不正确") # 登录成功后,可在request里面取值
class TestView(APIView):
def get(self, request):
print(request.user)
print(request.auth)
return Response("登陆后发送的数据") 5. 局部配置
1. 如果只是某些路由需要认证,那么可以局部设置认证,包括版本也可以局部认证 2. 把settings的配置注释掉 3. 在需要认证的视图中声明
from utils.auth import MyAuth class TestView(APIView):
authentication_classes = [MyAuth, ] # 局部配置认证组件
# versioning_class = [] # 局部配置版本组件
def get(self, request):
print(request.user)
print(request.auth)
return Response("登陆后发送的数据") 6. DRF提供的认证模块
from rest_framework import authentication
一般来说我们做认证不会使用DRF默认的认证类,只会继承它认证的基础类,
然后自己重写一个认证类,或者使用插件进行认证。

三、权限

1、权限是什么

权限一般也跟用户认证相关联,因为认证后,才知道我们的账号是什么角色,
比如博客、论坛数据库之类的,听说过管理员这个角色吧,
我们申请博客的时候就是向管理员申请,也就是说管理员会有一些特殊的权利,而我们没有。
这些对某件事情决策的范围和程度,我们叫做权限,权限是我们在项目开发中非常常用到的。

2、图解原理

3、使用

0. 如何表示你有权限
我们的权限类必须重写has_permission方法,和一个错误信息message,
根据登录后的用户的类型(认证后用户有自己的用户类型)决定是否给这个用户操作某些事情。 1. models
class User(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
token = models.UUIDField(null=True, blank=True)
CHOICES = ((1, "vip"), (2, "普通用户"), (3, "vvip"))
type = models.IntegerField(choices=CHOICES, default=2) # 用户类型 2. utils/permission.py
from rest_framework import permissions class MyPermission(permissions.BasePermission):
message = '权限不足' def has_permission(self, request, view):
# 判断是什么用户
if request.user.type in [1, 3]:
return True
return False 3. 视图
class PermissionView(APIView):
# 这个接口普通用户不能进入
permission_classes = [MyPermission, ] # 局部设置
authentication_classes = [MyAuth, ]
def get(self, request):
return Response('权限测试接口') 4. DRF提供的权限模块
from rest_framework import permissions 可根据时间需求使用

四、小结

1、如何使用自定义的类实现各种组件的功能

你能大概把源码里面组件的实现流程走通了,你就会知道自定义的类需要重写什么方法,返回值是什么,
或者百度到使用方法,硬把使用流程记下来。

2、一些小知识

1. 在DRF的接口中,一般是api_settings.xxx的,说明这个变量是默认配置项,你可以在你的settings里面通过重写REST_FRAMEWORK这个字典把它覆盖掉,
但是在settings里面配置的都是影响全局的,就是说所有视图都要遵守的,
如果想要局部设置,那么就在需要设置的视图里面配置相应的设置。
例如: # 全局配置
REST_FRAMEWORK = {
# 配置版本控制类
'DEFAULT_VERSIONING_CLASS': 'utils.version.MyVersion',
# 默认版本
'default_version': 'v1',
# 可用版本
'allowed_versions': ['v1', 'v2'],
# 参数
'version_param': 'version', # 配置认证类
'DEFAULT_AUTHENTICATION_CLASSES':['utils.auth.MyAuth', ] # 这样配是全局 # 权限类
'DEFAULT_PERMISSION_CLASSES': ['utils.permission.MyPermission', ]
} # 局部设置
class xxx(APIView):
versioning_class = MyVersion
permission_classes = [MyPermission, ]
authentication_classes = [MyAuth, ]
def get(self, request):
return Response('xxx') 2. APIView的各种组件默认值
class APIView(View): # The following policies may be set at either globally, or per-view.
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
metadata_class = api_settings.DEFAULT_METADATA_CLASS
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS 3. 注意
一般我们自定义的类都会继承DRF框架提供的对应的Base类
可以不继承的,但是继承的好处是,我们知道了要重写的方法,继承后,你重写方法时会有提示

DRF之版本控制、认证和权限组件的更多相关文章

  1. drf框架中认证与权限工作原理及设置

    0909自我总结 drf框架中认证与权限工作原理及设置 一.概述 1.认证 工作原理 返回None => 游客 返回user,auth => 登录用户 抛出异常 => 非法用户 前台 ...

  2. rest-framework组件 之 认证与权限组件

    浏览目录 认证组件 权限组件 频率组件 认证与权限组件 认证组件 局部视图认证 在app01.service.auth.py: class Authentication(BaseAuthenticat ...

  3. DRF(4) - 认证、权限组件

    一.引入 通过前面三节课的学习,我们已经详细了解了DRF提供的几个重要的工具,DRF充分利用了面向对象编程的思想,对Django的View类进行了继承,并封装了其as_view方法和dispatch方 ...

  4. DRF 版本、认证、权限、限制、解析器和渲染器

    目录 一.DRF之版本控制 为什么要有版本控制? DRF提供的版本控制方案 版本的使用 全局配置 局部配置(使用较少) 二.DRF之认证 内置的认证 步骤 三.DRF之权限 1.自定义一个权限类 2. ...

  5. rest-framework认证、权限组件

    认证组件: models class User(models.Model): username = models.CharField(max_length=32) password = models. ...

  6. rest_famework 认证与权限组件

    定义个一个认证类 from rest_framework import exceptionsfrom rest_framework.authentication import BaseAuthenti ...

  7. Restful 4 -- 认证组件、权限组件、频率组件、url注册器、响应器、分页器

    一.认证组件.权限组件.频率组件总结:  只有认证通过的用户才能访问指定的url地址,比如:查询课程信息,需要登录之后才能查看,没有登录,就不能查看,这时候需要用到认证组件 1.认证组件格式 写一个认 ...

  8. RESTful-rest_framework认证组件、权限组件、频率组件-第五篇

    认证组件.权限组件.频率组件总结:  认证组件格式: 1 写一个认证类 from rest_framework.authentication import BaseAuthentication cla ...

  9. rest_framework组件之认证,权限,访问频率

    共用的models from django.db import models # Create your models here. class User(models.Model): username ...

随机推荐

  1. 过滤器(Filter)和拦截器(Interceptor)

    过滤器(Filter) Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序.它依赖于servlet容器,在实现上,基于函数回调,它可以对几乎所有请求 ...

  2. Object.keys 及表单清空

    Object.keys 返回一个所有元素为字符串的数组,其元素来自于从给定的object上面可直接枚举的属性.这些属性的顺序与手动遍历该对象属性时的一致. // simple array var ar ...

  3. jupyter notebook安装、登录

    pip install jupyter 提示pip需要升级(本人装的是anaconda) 输入:python -m pip install --upgrade pip 安装完成. 运行jupyter ...

  4. Linux 环境 Maven 安装&仓源配置

    索引: 目录索引 参看代码 GitHub: maven.txt 一.Linux (DeepinOS) 环境 1.官网下载 https://maven.apache.org/download.cgi 2 ...

  5. sql server 错误日志errorlog

    一 .概述 SQL Server 将某些系统事件和用户定义事件记录到 SQL Server 错误日志和 Microsoft Windows 应用程序日志中. 这两种日志都会自动给所有记录事件加上时间戳 ...

  6. Python生成器、推导式之前襟后裾

    生成器 函数体内有yield选项的就是生成器,生成器的本质是迭代器,由于函数结构和生成器结构类似,可以通过调用来判断是函数还是生成器,如下: def fun(): yield "我是生成器& ...

  7. ZooInspector 连接不到 Zookeeper 的解决方法

    Zookeeper正常启动后,在使用 ZooInspector 连接 Zookeeper 时出现了连接不上的问题. [root@localhost bin]# zkServer.sh start Zo ...

  8. socketServer并发处理socket

    socketserver简单介绍 ''' socketserver:是对socket的封装,实现并发处理 前两个TCP,UDP常用,后两个不常用 ''' import socketserver soc ...

  9. django自定义分页器

    一 django 的分页器 1 批量创建数据 批量导入数据: Booklist=[] for i in range(100): Booklist.append(Book(title="boo ...

  10. c#语法学习

    自动属性.隐试类型.命名参数和自动初始化器. note:这里说的这些,是语法糖.按照一定的格式写,部分代码编译器帮我们实现了, 1.自动属性:自动属性是非常有用的语法糖,帮我我们做了两件事:1.自动帮 ...