Django-DRF認證,許可權,限頻,過濾,排序
阿新 • • 發佈:2020-12-01
一、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,]