drf : 頻率原始碼分析
阿新 • • 發佈:2022-04-11
頻率元件
一、自定義頻率元件
自定義的邏輯
#(1)取出訪問者ip
# (2)判斷當前ip不在訪問字典裡,新增進去,並且直接返回True,表示第一次訪問,在字典裡,繼續往下走
# (3)迴圈判斷當前ip的列表,有值,並且當前時間減去列表的最後一個時間大於60s,把這種資料pop掉,這樣列表中只有60s以內的訪問時間,
# (4)判斷,當列表小於3,說明一分鐘以內訪問不足三次,把當前時間插入到列表第一個位置,返回True,順利通過
# (5)當大於等於3,說明一分鐘內訪問超過三次,返回False驗證失敗
原始碼實現:
class MyThrottles(): VISIT_RECORD = {} def __init__(self): self.history=None def allow_request(self,request, view): #(1)取出訪問者ip # print(request.META) 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])
二、內建頻率元件
第一步 需要寫一個頻率類 繼承SimpleRateThrottle
1.1 重寫get_cache_key 返回self.get_ident(request)
1.2 重點 一定要配置一個scop=一個字串
class Throttle(SimpleRateThrottle): scope = 'zk' def get_cache_key(self, request, view): # 返回什麼值就以什麼做過濾,返回使用者的ID 就用使用者id過濾 return self.get_ident(request) # 內部其實返回的還是一個ip地址
第二步 在settings中配置
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES':{
'zk':'3/m' 主要是前面是m就行 後面隨便寫什麼都可以
}
區域性使用:
class Books(APIView):
throttle_classes = [Throttle, ] # 區域性
# throttle_classes = []
def get(self, request):
return Response('qqqqq')
全域性使用:
REST_FRAMEWORK = {
# 加一下這段話就行 這裡注意的小bug就是 頻率類不能再vies裡面寫 不然會報差錯
'DEFAULT_THROTTLE_CLASSES': ['app01.utils.VisitThrottle.Throttle', ],
'DEFAULT_THROTTLE_RATES': {
'zk': '3/minute',
}
}
區域性禁用:
class Books(APIView):
throttle_classes = [] # 區域性禁用
def get(self, request):
return Response('qqqqq')
三、原始碼分析
1.首先進來先走as.view() 這裡的as.view() 就是APIView 所以進入到APIView
2.因為APIView是的as.view() 是繼承了父類的as.view()方法也就是View()類 在view()類中的as.view()是返回了dispatch()
方法所以我們進入dispatch()方法
3.進入initial()方法,找到最後一個就是我圈中的那個方法,就是頻率元件
4.進入頻率元件方法
5.進入get_throttles()
6.由於我分析的是系統內建的頻率元件,然後系統內建的也是會呼叫到allow_request()方法,不管你是內建的頻率元件還是
自定義的頻率元件,都會重寫allow_request(),所以程式走到這一步,由於是分析系統內建的頻率元件,然後自己本身沒有allow_request()
這個方法,所以會去他繼承的父類去找這個方法。
7.進入SimpleRateThrottle()這個方法,點選圖片下方的小圓圈,定位到當前程式碼,然後進入
allow_request()方法。
8.呼叫SimpleRateThrottle的時候就會進去載入他的__init__方法
9.進入parse_rate()方法拿到他的返回值 分別是3和60
10進去到自己本身繼承的類的allow_request()方法
11.進入到rate的方法檢視他的原始碼
12 結束