一、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,]