1. 程式人生 > 其它 >drf : 頻率原始碼分析

drf : 頻率原始碼分析

頻率元件

一、自定義頻率元件

自定義的邏輯

#(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 結束