drf08

内容概要

  • 认证,权限,频率源码分析
  • 基于APIView编写分页
  • 异常处理

前戏

我们先看,drf 的三大认证怎么执行的

执行就是在调用APIView的dispatch

我们得先知道这个self是谁,现在的self是在view中用我们自己的写的视图类产生的对象。所以现在的self是我们的视图类对象

image-20230208175743611

image-20230208180228269

所以是先执行认证,在执行权限,频率

那就去看认证的源码

认证类的执行源码

image-20230208180740421

image-20230208180835817

image-20230208180948709

image-20230208181308905

image-20230208181442728

image-20230208181659559

image-20230208181922139

image-20230208182121362

image-20230208182404892

image-20230208183228226

image-20230208183329205

总结:

认证类,可多个,返回None则执行下一个认证类,返回用户类,和token(或返回两个值)则停止认证

去执行权限认证。

权限类的执行源码

image-20230208180228269

image-20230208183943924

image-20230208184115659

image-20230208184354456

image-20230208185550503

image-20230208185728584

总结

当你有多个权限认证类的时候只要有一个权限没有通过则

就不在执行后续代码

频率源码分析

image-20230208180228269

image-20230208201411596

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

image-20230208202232638

image-20230208202402901

image-20230208202522637

image-20230208202605657

image-20230208203013334

image-20230208203429934

image-20230208203633297

然后把提示信息个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源码分析

image-20230208213627796

image-20230208213842086

image-20230208213958881

image-20230208214527549

image-20230208214736186

基于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)
            ]))

image-20230208224210579

异常处理

APIView----》dispatch-------》三大认证,视图类的方法,如果出错会被捕获,捕获后统一处理

drf内置了一个函数,只要上面过程中出现了异常,就会执行这个函数,这个函数只处理drf的异常

image-20230208231254773

image-20230208231414393

image-20230208231517529

image-20230208231604213

image-20230208231658974

image-20230208231857705

image-20230208231928445

总结

我们只要重写 那个从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',
}
posted @ 2023-02-08 23:43  可否  阅读(18)  评论(0)    收藏  举报