drf08
内容概要
- 认证,权限,频率源码分析
- 基于APIView编写分页
- 异常处理
前戏
我们先看,drf 的三大认证怎么执行的
执行就是在调用APIView的dispatch
我们得先知道这个self是谁,现在的self是在view中用我们自己的写的视图类产生的对象。所以现在的self是我们的视图类对象


所以是先执行认证,在执行权限,频率
那就去看认证的源码
认证类的执行源码











总结:
认证类,可多个,返回None则执行下一个认证类,返回用户类,和token(或返回两个值)则停止认证
去执行权限认证。
权限类的执行源码






总结
当你有多个权限认证类的时候只要有一个权限没有通过则
就不在执行后续代码
频率源码分析


返回了我们需要限制的,是ip还是用户id。







然后把提示信息个Response给前端
总结:
-我们写的频率类:继承BaseThrottle,重写allow_request,在内部判断,如果超频了,就返回False,如果没超频率,就返回True
自定义频率类基于BaseThrottle
from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
import time
class CommThrottle(BaseThrottle):
default_dict = {}
def __init__(self):
self.res = None
def allow_request(self, request, view):
# print(self.default_dict)
# 自己写逻辑,判断是否超频
# (1)取出访问者ip
ip = request.META.get("REMOTE_ADDR", None)
# (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走 {ip地址:[时间1,时间2,时间3,时间4]}
# {"ip":[时间1,时间2]}
if ip in self.default_dict:
time_list = self.default_dict.get(ip)
# (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
while time_list and time.time() - time_list[-1] > 60:
time_list.pop()
# (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
if len(time_list) < 3:
time_list.insert(0, time.time())
return True
# (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
else:
return False
else:
self.default_dict[ip] = [time.time()]
# (1)取出访问者ip
print(self.default_dict)
return True
SimpleRateThrottle源码分析





基于APIView编写分页
class BooksView(ViewSet, ):
def list(self, request):
# 获取全部数据
books = Book.objects.all()
# 序列化
serializer1 = BookSerializer
# 生成分页器对象
page_obj = CommonPageNumberPagination()
# 分页器对象调用方法
page = page_obj.paginate_queryset(books, request, self)
if page is not None:
# 序列化 数据
serializer = serializer1(page, many=True)
# 传给前端
# return Response(serializer.data)
# 用默认的
# return page_obj.get_paginated_response(serializer.data)
# 定制返回数据
return Response(dict([
('total', page_obj.page.paginator.count),
('next', page_obj.get_next_link()),
('previous', page_obj.get_previous_link()),
('results', serializer.data)
]))

异常处理
APIView----》dispatch-------》三大认证,视图类的方法,如果出错会被捕获,捕获后统一处理
drf内置了一个函数,只要上面过程中出现了异常,就会执行这个函数,这个函数只处理drf的异常







总结
我们只要重写 那个从settings里找的那个函数
只要它返回一个Response对象就能捕获全部的异常
from rest_framework.views import exception_handler
from rest_framework.response import Response
def myexcption(exs, context):
res = exception_handler(exs, context)
if res:
return res
else:
return Response("请联系管理员")
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app01.myex.myexcption',
}

浙公网安备 33010602011771号