Django-DRF认证,权限,限频,过滤,排序

一、DRF自定义认证使用

# 1 定义一个类,继承BaseAuthentication,重写authenticate方法
class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        token = request.GET.get('token')
        res = models.UserToken.objects.filter(token=token).first()
        if res:
            return 元组  
        # 返回空或者元组,若返回元组则必须有两个值,第一个为self.request,第二个self.auth,self是request对象
        else:
            raise AuthenticationFailed('您没有登录')

            
# 2 使用位置
-局部使用:在视图类中配置
authentication_classes = [MyAuthen.LoginAuth, ]  # 是个列表,可以写多个认证类,其中一个有返回值则不会执行后面
-局部禁用:在视图类中配置空
authentication_classes = []
-全局使用:在settings中使用
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.MyAuthen.LoginAuth", ]
}
   
    
# 3 注意:
	1 认证类,认证通过可以返回一个元组,有两个值,第一个值会给,request.user,第二个值会个request.auth
    2 认证类可以配置多个,按照从前向后的顺序执行,如果前面有返回值,认证就不再继续往下走了

二、DRF自定义权限使用

权限的校验在认证之后,所以可以拿到前面return的request.user和request.auth

# 1 使用写一个类继承BasePermission,重写has_permission

# 假设某个视图中,超级用户为1,可以访问,除了超级用户以外,都不能访问
class SuperPermission(BasePermission):
    # 若要打印中文错误信息可以在类中写message
    # message='错误信息提示'
    def has_permission(self, request, view):
        if request.user.user_type == '1':  # 此处使用了request.user需要认证里返回来,若不返回就拿不到
            return True
        else:
            return False

        
# 2 使用位置
-局部使用
permission_classes = [MyAuthen.SuperPermission,]
-局部禁用
permission_classes = []
-全局使用
REST_FRAMEWORK = {
    "DEFAULT_PERMISSION_CLASSES": ["app01.MyAuthen.SuperPermission", ]
}

三、DRF自定义限率使用

1.自己写一个,根据ip限制访问频率

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

from rest_framework.throttling import BaseThrottle

class MyThrottle(BaseThrottle):
    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.自定义限制频率的步骤

下面的SimpleRateThrottle已经帮我们实现了根据ip限制访问频率

# 1 写一个类,继承SimpleRateThrottle
class MySimpleThrottle(SimpleRateThrottle):
    scope = 'xxx'
    def get_cache_key(self, request, view):
        #什么都不写,就默认以ip限制
        return self.get_ident(request)
    
-setting.py中配置
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES' : {
        'xxx':'10/m'
        '''
        key跟scope对应,value是一个时间,表示每分钟十次,可以自己改,底层是用/分割,
        然后取右边第一个索引,所以写'10/mcbiaba'或'10/m'没区别
        '''
    }
}


# 2 使用位置
-局部使用
throttle_classes = [auth.MyThrottle,]
-局部禁用
throttle_classes = []
-全局使用
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES':['app01.auth.MyThrottle',],
}

3.其他内置限制频率类与使用

# 内置频率类
BaseThrottle:基类
AnonRateThrottle:限制匿名用户的访问次数
SimpleRateThrottle:一般用来继承他,然后我们自定义
ScopedRateThrottle
UserRateThrottle:限制登录用户访问次数
    
    
# 其它内置频率类的使用
AnonRateThrottle:限制匿名用户的访问次数,根据ip限制

-局部使用
throttle_classes = [throttling.AnonRateThrottle]
-全局使用
-setting.py中配置
'DEFAULT_THROTTLE_RATES' : {
    'anon':'1/m'
}
    

UserRateThrottle:限制登录用户访问次数
-限制登录用户访问次数UserRateThrottle(根据用户id限制)

-局部使用
throttle_classes = [throttling.UserRateThrottle]
-全局使用
-setting.py中配置
'DEFAULT_THROTTLE_RATES' : {
    'user':'1/m'
}

四、DRF过滤与排序使用

对于查询的结果,一般我们还需要经过一些过滤或者排序。

DRF自己有内置的过滤功能,我们也可以使用第三方库,django-filter来过滤,也可以自己写自定义的过滤方法。

# 1 内置筛选的使用
-在视图类中配置
filter_backends =[SearchFilter,]
search_fields=('name',) # 表模型中的字段
-查询的地址
http://127.0.0.1:8000/students/?search=e  # 模糊查询
                
# 2 第三方扩展的过滤功能
-pip3 install django-filter  :最新版本(2.4.0)要跟django2.2以上搭配
-在视图类中配置
filter_backends =[DjangoFilterBackend,]
filter_fields=['name','age']
-查询的时候
http://127.0.0.1:8000/students/?name=lqz&age=18  # 精确查询
                
                
# 3 自定义:
# 写一个类MyFilter,继承BaseFilterBackend
from rest_framework.filters import BaseFilterBackend

# 重写filter_queryset方法,在该方法内部进行过滤(自己设置的过滤条件)并返回queryset
class MyFilter(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        # 自己的过滤
        return queryset

# 配置在视图类中
	filter_backends = [MyFilter,]
原文地址:https://www.cnblogs.com/chiyun/p/14066678.html