首页 > 其他分享 >drf-day14

drf-day14

时间:2023-09-21 14:47:51浏览次数:35  
标签:--- return self request 列表 day14 访问 drf

频率源码分析

频率源码

APIView----disaptch---》self.initial(request, *args, **kwargs)---》416行:self.check_throttles(request)----》352行 check_throttles
    
    def check_throttles(self, request):
        # self.get_throttles()就是咱们配置在视图类上频率类的对象列表[频率类对象,]
        for throttle in self.get_throttles():
            # 执行频率类对象的allow_request,传了2个,返回True或False
            if not throttle.allow_request(request, self):
                # 反会给前端失败,显示还剩多长时间能再访问
                throttle_durations.append(throttle.wait())

频率逻辑

1 写一个类,继承,BaseThrottle
2 在类中重写:allow_request方法,传入 3个参数
3 在allow_request写限制逻辑,如果还能访问--》返回True
4 如果超了次数,就不能访问,返回False
5 局部配置在视图类上
6 全局配置在配置文件中

SimpleRateThrottle 源码分析

SimpleRateThrottle内部一定有:allow_request---》
    def allow_request(self, request, view):
        # 咱们没写,以后咱们可以在频率类中直接写
        # rate='3/m'   以后不用写scope了,就会按一分钟访问3次现在
        if self.rate is None:
            return True
        # 取出:重写的get_cache_key返回的值,咱们返回了访问者ip
        self.key = self.get_cache_key(request, view)
        if self.key is None:
            return True
        # 根据当前访问者ip,取出 这个人的访问时间列表  [访问时间1,访问2,访问3,访问4]
        self.history = self.cache.get(self.key, [])
        # 取出当前时间
        self.now = self.timer()
        # 把访问时间列表中超过 限制时间外的时间剔除
        while self.history and self.history[-1] <= self.now - self.duration:
            self.history.pop()
        # 判断访问时间列表是否大于 3 
        if len(self.history) >= self.num_requests:
            return self.throttle_failure()
        return self.throttle_success()

自定义频率类,实现一分钟只能访问三次的控制

(1)取出访问者ip
(2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
(3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
(4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
(5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
我们在drf中写的时候,不需要继承 BaseThrottle,继承了SimpleRateThrottle,重写get_cache_key

自定义频率类

from rest_framework.throttling import BaseThrottle


class MyThrottle(BaseThrottle):
    # VISIT_RECORD = {'192.168.1.1':[当前时间,当前时间,访问时间列表]}
    VISIT_RECORD = {}

    def __init__(self):
        self.history = []

    def allow_request(self, request, view):
        ip = request.META.get('REMOTE_ADDR')
        import time
        ctime = time.time()
        # (2)判断当前ip不在访问字典里,说明是第一次访问,添加进去,并且直接返回True,表示第一次访问
        if ip not in self.VISIT_RECORD:
            self.VISIT_RECORD[ip] = [ctime, ]  # VISIT_RECORD = {'192.168.1.1':[当前时间2,当前时间1,]}
            return True
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
        self.history = self.VISIT_RECORD[ip]  # 访问时间列表
        while self.history and ctime - self.history[-1] > 60:  # 循环删除1分钟之前访问的实际
            self.history.pop()

        # 最后self.history都剩下是一分钟之内的时间了
        # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
        # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
        if len(self.history) < 3:
            self.history.insert(0, ctime)
            return True
        else:
            return False

    def wait(self):
        import time
        ctime = time.time()
        return 60 - (ctime - self.history[-1])

过滤排序分页全局异常

过滤

#1 针对于查询所有接口---》继承:GenericAPIView+ListModelMixin---》只需要在视图类中写一个类属性---》filter_backends = [过滤类,过滤类2]


# 过滤类:
    1 内置的:SearchFilter  类属性:search_fields=[可以按字段过滤]
        127.0.0.1:8080/books/?search=红
    2 第三方
        -django-filter
        -精准匹配
         127.0.0.1:8080/books/?name=红楼梦
        -能更强大
    3 自定义的
        写一个类,继承:BaseFilterBackend
        重写 filter_queryset
        在filter_queryset中完成过滤,会把qs传入,返回过滤后的qs即可

# 2 源码分析
    ListModelMixin---》list方法---》queryset = self.filter_queryset(self.get_queryset()) 过滤后的数据----》执行了GenericAPIView的---》filter_queryset---》取出一个个配置在视图类上的过滤类,依次实例化得到对象后执行对象的filter_queryset方法完成过滤---》最终返回的数据,就是过滤后的数据
    
    
 # 3 继承APIView写过滤
    request 取出过滤条件
    book_list=Book.objects.all().filter(过滤)

排序

1 针对于查询所有接口---》继承:GenericAPIView+ListModelMixin---》只需要在视图类中写一个类属性---》filter_backends = [排序类]
2 内置排序类即可:OrderingFilter---》配置类属性ordering_fields

分页

分页三种方式

 三种分页方式,必须继承分页类,重写几个类属性实现--->配置在视图类上--》继承:GenericAPIView+ListModelMixin
PageNumberPagination:用的最多,之前常见的分页方式,查询第几页,每页有多少条的分页方式 :page=10&size=3
LimitOffsetPagination:从第几条开始,取几条  offset=10&limit=3  从第10条开始,取3条
CursorPagination:只能上一页和下一页,需要排好序再分页

继承APIView 写分页

class  Pager(APIView):
    def get(self,request,*args,**kwargs):
        # 获取所有数据
        ret=models.Book.objects.all()
        # 创建分页对象
        page=PageNumberPagination()
        # 在数据库中获取分页的数据
        page_list=page.paginate_queryset(ret,request,view=self)
        # 对分页进行序列化
        ser=BookSerializer1(instance=page_list,many=True)
        # return Response(ser.data)
        # 这个也是返回Response对象,但是比基本的多了上一页,下一页,和总数据条数(了解即可)
        return page.get_paginated_response(ser.data)
        return Response(ser.data) # 只会有数据,不会有上一页和下一页,总条数

全局异常

# 前后端分离了,后期,后端出了异常,我们不想让前端看到,我们需要捕获全局异常,统一返回格式

# drf 源码中已经处理
    APIView--->dispatch--->
     try:
        # 1 执行三大认证
        # 2 执行视图类的方法
    except Exception as exc:
        response = self.handle_exception(exc)
        
    -463行左右:
    # exception_handler就是配置文件中配置的一个函数-->默认的
    # 后期自己写了
    exception_handler = self.get_exception_handler()
    response = exception_handler(exc, context)
    
# 默认执行的是:rest_framework.views.exception_handler函数---》只处理了drf的异常    
# 咱们处理全局异常的步骤:
    1 写一个函数,在内部处理
    from rest_framework.views import exception_handler
    def common_exception_handler(exc,context):
        res=exception_handler(exc,context)
        if res: #这次异常是drf的,并且它处理了
            # 我们要统一返回格式
            return Response({'code':888,'msg':"系统异常(drf异常),请联系系统管理员:%s"%res.data.get('detail',None)})
        else:
            return Response({'code': 999, 'msg': "系统异常(非drf异常),请联系系统管理员:%s" % str(exc)})
    2 配置在配置文件上

接口文档

# 接口写完,必须编写接口文档,给别人用

# 接口文档规范:要有什么东西
    1 描述
    2 地址
    3 请求方式
    4 请求编码格式
    5 请求参数,详解
    6 返回示例  json
    7 返回示例中字段详解
# 编写的位置:
    1 直接写在文件中共享(word,md)
    2 平台上写
        - 公司搭建的平台(自己研发,第三方开源)
        - 使用第三方接口文档平台
    3 自动生成
        -coreaip

JWT认证

JWT认证

json web tokne缩写,一种前后端认证的方法,区别与session的方案,不需要在后端存储数据,也能实现会话保持

JWT原理

三段式:
    签发阶段
        登录:
            用户名+密码
            手机号+验证码
            本机号码一键登录--》向后端就只传了手机号--》根据手机号签发token
            
    认证阶段
    drf中的认证类
            校验token是否合法

别人截获到token后,模拟发送请求

解决方法

1 设置过期时间---》10m
2 需要登录后才能访问的接口,不仅要带token还是带个加密串 sign
3 双token认证
       返回两个token:一个token:7天过期,一个token:10分钟过期
       以后用就只带10分钟过期的token
       过了10分钟了,10分钟token失效了
       携带着7的token到后端,生成一个10分钟的返回
           原来的token串使用md5+盐生成一个串--》签名

自定义用户表

多方式登录

权限控制

acl:访问控制列表

用户跟权限多对多

基于角色的访问控制 rbac

用户跟角色关系,角色和权限管理
    用户表
    角色表
    权限表
    用户和角色多对多中间表
    角色和权限多对多中间表
    用户和权限多对多

abac:
基于属性+角色的访问控制

  基于属性+访问控制列表
        张三:【看视频,发视频】
        张三:晚上12点凌晨7点 不能发视频

 

标签:---,return,self,request,列表,day14,访问,drf
From: https://www.cnblogs.com/shanghaipudong/p/17702607.html

相关文章

  • drf(序列化器)
    一序列化器组件介绍(Serializer)1序列化器组件介绍序列化组件,又称序列化器,是处理对象和字典的数据格式转换,json的序列化和反序列化,在Request和Response处理了。'''1序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串2反系列化,把客户端发送过来的数据......
  • drf(初始drf,restfull规范 ,源码)
    一web开发模式#前后端混合开发(前后端不分离):通过模版语法,在服务器上处理好html的内容(组合字符串),返回给浏览器一堆字符串(字符串封装到respons对象里),浏览器在渲染#前后端分离:只专注于写后端接口,返回json、xml格式#xml比json笨重#补充:什么是动态页面(需要查数据......
  • DRF之分页类源码分析
    【一】分页类介绍DjangoRESTframework(DRF)是一个用于构建WebAPI的强大工具,它提供了分页功能,使你能够控制API响应的数据量。在DRF中,分页功能由分页类(PaginatorClass)来管理。【二】内置分页类在DRF中,分页类通常位于rest_framework.pagination模块中,它们用于分割长列表或......
  • DRF之排序类源码分析
    【一】排序类介绍在DjangoRESTframework(DRF)中,排序类用于处理API端点的排序操作,允许客户端请求按特定字段对数据进行升序或降序排序。排序类是一种特殊的过滤类DRF提供了内置的排序类,并且你也可以自定义排序类以满足特定的需求。【二】内置排序类OrderingFilterrest_f......
  • DRF之JWT签发Token源码分析
    【一】JWT介绍JWT(JSONWebToken)是一种用于身份认证和授权的开放标准(RFC7519)。它基于JSON格式定义了一种安全的令牌,用于在客户端和服务器之间传输信息。【二】JWT三段式JWT(JSONWebToken)是一种用于身份认证和授权的开放标准(RFC7519)。它基于JSON格式定义了一种安全的令......
  • elementplus django drf 如何做到确认单据禁止删除
    elementplusdjangodrf如何做到确认单据禁止删除  要在Django和DjangoRestFramework(DRF)中实现禁止删除确认单据的功能,你可以通过以下步骤来完成:创建模型:首先,你需要在Django中创建一个模型来表示确认单据。这个模型应该包含与确认单据相关的所有信......
  • Django框架高级之DRF部分源码分析
    【一】DRF之请求执行流程和APIView源码分析【二】DRF之Request源码分析【三】DRF之Response源码分析【四】DRF之登录认证源码分析......
  • DRF之Response源码分析
    【一】响应类的对象Response源码【1】路由fromdjango.contribimportadminfromdjango.urlsimportpathfrombookimportviewsurlpatterns=[path('admin/',admin.site.urls),path('test/',views.TestView.as_view()),]【2】视图fromrest_frame......
  • drf
    目录接口规范WebAPI接口接口测试工具Restful接口规范DjangoRest_Framework序列化组件序列化和反序列化序列化组件介绍快速使用常用字段类和参数序列化组件之校验基于APIVIew+Response+序列化类的5个接口反序列化之更新source用法SerializerMethodField定制字段多表关联序列化和......
  • drf整合
    drf内容简介1.drf入门规范2.序列化组件----(最重要)3.请求与响应4.视图组件----(重要)5.路由组件6.认证、权限、频率----(重要)7.过滤、排序、分页、全局异常处理8.接口文档9.jwt认证10.权限:ACL、RBAC drf入门规范前后端开发模式前后端混合开发模式: ......