其他分享
首页 > 其他分享> > 自定义频率类,全局异常处理

自定义频率类,全局异常处理

作者:互联网

1 自定义频率类

# 自定义的逻辑
#(1)取出访问者ip   {192.168.1.12:[访问时间3,访问时间2,访问时间1],192.168.1.12:[],192.168.1.14:[]}
#(2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
#(3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
#(4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
#(5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败

1.1 具体实现

from rest_framework.throttling import BaseThrottle
class MyThrottling():
    VISIT_RECORD = {}

    def __init__(self):
        self.history = None
    def allow_request(self, request, view):
        # (1)取出访问者ip
        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, ]
            return True
        self.history = self.VISIT_RECORD.get(ip)
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
        while self.history and ctime - self.history[-1] > 60:
            self.history.pop()
        # (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])

2 权限,频率执行源码分析(了解)

2.1 权限源码执行流程

# APIView的dispatch---》self.initial(request, *args, **kwargs)---》415行self.check_permissions(request)--->
    def check_permissions(self, request):
        for permission in self.get_permissions(): #配在视图类上的权限类列表对象
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                )

2.2 频率源码执行流程

# APIView的dispatch---》self.initial(request, *args, **kwargs)---》416行self.check_throttles(request)--->
  def check_throttles(self, request):
        throttle_durations = []
        for throttle in self.get_throttles(): # 配在视图类上频率类列表 频率类的对象
            if not throttle.allow_request(request, self):
                throttle_durations.append(throttle.wait())
        if throttle_durations:
            durations = [
                duration for duration in throttle_durations
                if duration is not None
            ]

            duration = max(durations, default=None)
            self.throttled(request, duration)
            
# 你写的频率类一定要重写allow_request,返回True就是没有频率限制住,返回False就是被频率限制了

# 咱们第一天写的,继承SimpleRateThrottle---》它肯定重写了allow_request---》今天写的逻辑跟源码一样
SimpleRateThrottle---》allow_request---》
	def __init__(self):
        if not getattr(self, 'rate', None):
            # self.rate 现在是  '3/m'
            self.rate = self.get_rate()
        # 3                   60
        self.num_requests, self.duration = self.parse_rate(self.rate)
    def allow_request(self, request, view):
        if self.rate is None:  # 只要配在文件配了,它就有值,在init中
            return True

        # 现在的唯一字符串
        # ip地址
        self.key = self.get_cache_key(request, view)
        if self.key is None:
            return True

        # [时间2,时间1]
        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() #把所有超过60的数据都剔除,self.history只剩60s以内的访问时间
        if len(self.history) >= self.num_requests:  #大于等于配置的数字3 
            return self.throttle_failure() # return False
        return self.throttle_success()  # 把当前时间插入,retrun True

3 全局异常处理(重要)

# drf配置文件中,已经配置了,但是它不符合咱们的要求
# drf的配置文件:'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
# 如果抛了异常,就会执行exception_handler函数

# 重新写一个函数,如果出了异常,执行我们的函数

# drf默认的异常处理,只处理了drf自己的异常:所有drf中抛的异常,都有detail,django的异常,抛出很长的xml数据


{
    "detail": "小伙子,你错了"
}

{	
    code:999
 	msg:"小伙子,你错了"
}

使用步骤

# 第一步:写一个函数
from rest_framework.views import exception_handler
from rest_framework.response import Response
def common_exception_handler(exc, context):
    # 正常来讲,在这里需要记录日志---》如何在django中记录日志后面讲
    # 日志记录,越详细越好:哪个用户(id,ip),在什么时间,执行哪个视图函数时报了错,请求地址是什么
    print(context['view'])  #视图类的对象
    print(context['request']) #当前请求的对象----》ip,用户id,当前时间,请求地址来
    view=context['view']
    request=context['request']
    print('ip地址为:%s的用户,访问:%s 视图类,报错了,请求地址是:%s'%(request.META.get('REMOTE_ADDR'),str(view),request.path))

    response=exception_handler(exc, context)
    if response: # 这是drf的异常,其实人家已经处理了,但是不符合我的格式  {code:999,msg:错误}
        res=Response({'code':999,'msg':response.data.get('detail')})
    else:
        # res=Response({'code':998,'msg':'服务器错误,请联系系统管理员'})
        res=Response({'code':998,'msg':str(exc)})

    return res
# 第二步:把函数配置在配置文件中
	REST_FRAMEWORK = {
    # 自己写的全局异常捕获
        'EXCEPTION_HANDLER': 'app01.exceptions.common_exception_handler',
    }

4 自动生成接口文档

# 后端人员,写好接口,提供接口文档给前端用

# 如何编写接口文档
	-使用word写,md写----》提交到git上
    -公司有接口文档平台---》后端人员在文档平台录入数据---》公司自己开发,yapi(百度开源),第三方
        -https://zhuanlan.zhihu.com/p/366025001  自己搭建yapi
        -https://www.showdoc.com.cn/  第三方平台
    - 自动生成接口文档---》项目写好了,一键生成接口文档----》一键生成---》导出---》导入到yapi

# drf中自动生成接口文档
	-coreapi,swagger(更通用一些,go,java)
	-安装 pip3 install coreapi
    -在项目中配置	
    	-加入路由:
        from rest_framework.documentation import include_docs_urls
        urlpatterns = [
            path('docs/', include_docs_urls(title='站点页面标题'))
        ]
        -配置文件中配置
        REST_FRAMEWORK = {
         'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',

        }
        
        -尽管写接口,写注释,会自动生成
    

5 RBAC介绍(面试)

# RBAC  是基于角色的访问控制(Role-Based Access Control )在 RBAC  中,
权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便


# 这种设计,在公司内部系统用的多,对外的系统基本不用

# 权限:真正的权限,比如发工资,招人,申请测试机
# 角色:(组,部门) 角色下有很多员工
# 用户:一个个的人

# 用户和角色关系是多对多,中间表
# 权限和角色关系是多对多,中间表
# 权限和用户的中间表


#前后端分离项目控制权限---》权限类中
#前后端混合
	-django框架在公司里用的很多,写内部项目,肯定要用权限控制,用的就是rbac,自己实现一套,django内置了后台管理,自带rbac(admin+auth)
    -基于django的admin二次开发
    	-美化:xadmin(基本不用了,2.x以后django不兼容多,作者弃坑了)
        -simpleui:
    -django+drf+vue=djagnovueadmin  一款前后端分离的自带rbac的后台管理框架
    
    
    
# django的admin基于rbac
  	-auth_user  #用户表
    -auth_permission #权限表
    -auth_group  #组,角色表
    
	-auth_user_groups   # 用户和组中间表
    -auth_group_permissions  #组和权限中间表
    -auth_user_user_permissions #用户和权限中间表


标签:自定义,ip,self,request,---,频率,全局,权限,history
来源: https://www.cnblogs.com/chunyouqudongwuyuan/p/16402221.html