rest_framework认证,权限,节流,版本,解析器总结
建立后端项目,model模型,view视图,url路由配置
这里对应的就是我们写的model模型user用户和token信息表
一,认证组件
(1) 设置认证,只有通过的用户才能访问指定的url地址
(2) 写认证的类父元素是APIview,rest_framework源码dispatch里面调用了封装之后的request,调用initial方法里面调用了perform_authentication方法,返回的是user/auth俩值,我们写认证则要重新定义perform_authentication,根据token来匹配数据库做判断返回相对应的返回.
(3)写好之后需要在setting文件中配置
这里键是根据APIview下方设置的中间件来定义的
api_settings.DEFAULT_AUTHENTICATION_CLASSES
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES'['unitls.authentication.MyOrderAuthentication'],
}
(这里设置的是全局认证),如果是局部认证只需要在view中需要认证的地方写入
authentication_classes = [这里是自己定义的认证类]
**注意的是如果开启全局认证用户登录前需要关闭认证则要写入**
authentication_classes = []
注册成功之后要存数据库,用来后面登录做匹配
username = request._request.POST.get('username')
password = request._request.POST.get('password')
这里为们要用md5加码生成token然后保存
token = md5(username,password)
# 将token保存
UserToken.objects.update_or_create(
user=obj,defaults={'token':token},
)
保存后面登录根据 生成的token来做匹配判断
二,权限
(1) 给用户设置权限,只有登录用户并且是指定用户才能访问
(2) 和认证方法大致相同在initial方法下调用
self.check_permissions(request),进入到check_permissions函数中发现里面是做一个对象循环判断
if not permission.has_permission(request, self):
#在自定义的Permission中has_permission方法是必须要有的
#判断当前has_permission返回的是True,False,还是抛出异常
#如果是True则表示权限通过,False执行下面代码
#为False的话则抛出异常,当然这个异常返回的提示信息是英文的,如果我们想让他显示我们自定义的提示信息
#我们重写permission_denied方法即可
self.permission_denied(
#从自定义的Permission类中获取message(权限错误提示信息),一般自定义的话都建议写上,如果没有则为默认的(英文提示)
self.permission_denied(
request,message=getattr(permission,'message',None)
)
只需要更改message值就行比如
message ='你不是超级用户,没有权限访问'
(---------)例如我在下面写了一个判断3表示的是svip用户
def has_permission(self, request, view):
"""
Return `True` if permission is granted, `False` otherwise.
返回True表示有权限访问,返回False表示没有权限访问"""
if request.user.user_type !=3:
return False
return True
******全局配置
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES":[自己写权限类的路径]
}
三,节流
有些时候为了对用户的访问频率进行限制和防止爬虫,需要在规定的时间中对用户访问的次数进行限制
(1),源码入口dispatch--------->>执行认证 self.initial ------->>频率控制self.check_throttles(request)里面做循环判断,
for throttlein self.get_throttles():
if not throttle.allow_request(request, self):
self.throttled(request, throttle.wait())
如果没有通过会返回 false 执行 self.throttled(request, throttle.wait()),抛出异常---------返回True表示可以继续访问
def get_throttles(self):
# 返回访问频率控制的
return[throttle() for throttle in self.throttle_classes]--------------->>
所以说我们需要进行节流限制接口设置类属性
throttle_class = [ 节流限制的类 ]
我们需要重写allow_request(request, self) 和 wait 方法
**全局设置
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES":{
'unlogin':'10/m',
'logined':'3/m'
}
这里的unlogin和logined是我们在节流类下面写入----->>类:scope ='logined'
四,版本
1,类:在新版本上线,老版本不能直接删除情况下,用到版本控制
2, 进口dispatch ---->>initial下面有版本控制源码
version, scheme =self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
3,这里调用方法self.determine_version,进入看到
def determine_version(self, request, *args, **kwargs):
if self.versioning_classis None:
return (None,None)
scheme =self.versioning_class()
return (scheme.determine_version(request, *args, **kwargs), scheme)
(1)versioning_classis是在setting中定义的版本控制类
(2)versioning_class()进行定义的版本控制类实例化赋值给了scheme
(3) 最后return中 执行版本控制类中的determine_version方法,返回version,
4,scheme.determine_version的执行取决与我们所引用的版本控制类是哪一个,我们一般都用URLPathVersioning和QueryParameterVersioning
导入后点进入URLPathVersioning,里面发现调用is_allowed_version方法,这里做判断是否能访问当前版本
return((version is not None and version == self.default_version) or
(version in self.allowed_versions))
到这我们就获取到访问版本的类,回到开始-------------------------------
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
我们将version 和scheme封装在request中如果我们访问的版本符合要求我们可以通过调用
request.version, request.versioning_scheme 来获得版本号和控制版本的类
5,自己定义版本类模块,定义函数determine_version做版本控制配置路由要改变,,,,类:
url(r"^(?P<version>[v1|v2]+)/userinfo/", UserInfoView.as_view(),name='vvvv')
6,全局设置
'DEFAULT_THROTTLE_CLASSES':['unitls.throll.VisitThrottle'],
#设置版本的参数
'VERSION_PARAM':'version',
'DEFAULT_VERSION':'v1',
'ALLOWED_VERSIONS':['v1','v2'],
五,解析器
1,解析器是对我们请求体中的数据进行反序列化、封装 把我们的所有的请求数据都封装在request.data中 在request.data中获取数据
2,使用
(1)获取用户请求
(1)获取用户请求体
(3)根据用户请求头信息和parase_classes=[...],中的请求头进行比较,匹配上请求头就使用该解析器处理
(4)解析器从请求体中拿数据进行处理,处理完成之后将结果返回给request.data
-------------------------------------------------------------------
要导入模块
from rest_framework.parsers import FormParser, JSONParser
添加局部认证
parser_classes = [FormParser, JSONParser]
(1)然后获取数据,正常的post请求
浏览器中media_type形式为
media_type ='application/x-www-form-urlencoded'
(2)如果这里发送的是json数据则返回null空取不到数据
我们就可以在request的data中获取数据data = request.data