views.pyhtml
from rest_framework.throttling import BaseThrottle import time # 節流 visit_dict={} class Visitthrottle(BaseThrottle): #經過IP作惟一標識符 #問題:非登錄用戶一分鐘內只容許訪問3次 def __init__(self): self.history=None def allow_request(self,request, view): #獲取IP地址 remote_addr = self.get_ident(request) ctime=time.time() if remote_addr not in visit_dict: visit_dict[remote_addr]=[ctime,] return True self.history = visit_dict.get(remote_addr) while self.history and self.history[-1] <ctime - 60: self.history.pop() if len(self.history)<3: self.history.insert(0,ctime) return True def wait(self): ctime=time.time() return 60-(ctime-self.history[-1])
class TestThrottle(APIView): throttle_classes = [VisitThrottle,] def get(self, request, *args, **kwargs): pass ''' 等等一系列的視圖功能方法 '''
實現原理分析:python
settings.py:django
REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES':['api.utils.mythrottle.UserThrottle',] 'DEFAULT_THROTTLE_RATES': { '未認證用戶': '10/m', '已認證用戶': '100/h', }, }
mythrottle.py:api
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import exceptions from rest_framework.throttling import SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope = "未認證用戶" def get_cache_key(self, request, view): return self.get_ident(request) class UserThrottle(SimpleRateThrottle): scope = "已認證用戶" def get_cache_key(self, request, view): return request.user # 認證經過後,認證方法authenticate的返回值之一<br><br> class TestThrottle(APIView):<br> # 這樣設置後,節流功能就會使用VisitThrottle類,而不會使用UserThrottle類 throttle_classes = [VisitThrottle,] def get(self, request, *args, **kwargs): pass ''' 等等一系列的視圖功能方法 '''
這裏使用的節流類是繼承了SimplePateThrottle類,而這個類利用了django內置的緩存來存儲訪問記錄。經過全局節流設置,全部的視圖類默認是使用UserThrottle類進行節流,若是不想使用默認的類就自定義給throttle_classes屬性變量賦值,如:「throttle_classes = [VisitThrottle,]」。看到內置節流類的使用,可能一臉懵逼,下面進行源碼分析。緩存
與以前認證,權限控制的源碼分析方法一致,先進入函數入口dispatch方法,封裝完新的request對象後,進入initialize_request方法,咱們會發現還有一個函數調用咱們沒有分析,因此這就是咱們的節流函數。ide
1.爲何會使用scope屬性變量,有什麼用?函數
進入check_throttles函數,是否以爲很熟悉?沒錯在get_throttles方法中確定也是一個列表生產式,返回一個有節流類實例組成的列表。源碼分析
在列表生成式中,先對內置類SimplePateThrottle進行實例化,在實例化中去拿到scope的值,而且根據值做爲key值去配置文件中拿到對應value值。在parse_rate方法中能夠看出value是又‘/’分隔的一個字符串。spa
2.爲何會使用‘get_cache_key’方法,該方法的返回值是什麼?rest
實例化完成後,執行allow_request方法,首先執行的是get_cache_key’方法
在get_cache_key’方法中裏面什麼都沒寫,因此就是說咱們在使用內置節流類時,必須重構get_cacha_key方法,不然會拋出異常,由於內置節流類是經過django緩存實現,因此須要給它一個惟一標識符,在這裏我選擇的是選擇用戶的IP地址進行惟一確認,因此這裏的返回值爲一個惟一標識符。
接下來的操做與咱們自定義節流類的原理一致。最後若是返回false,調用wait方法,拋出異常
3.爲何使用‘throttle_classes’屬性變量,它有什麼用?
get_throttles方法返回的是一個列表生成式,而這裏的throttle_classes就是在視圖類TestThrottle中使用的,該變量就保存節流類對象。
4.‘DEFAULT_THROTTLE_CLASSES’從那裏來,有什麼用?
經過throttle_classes屬性變量,跳轉到該圖,能夠看到配置文件中說的「DEFAULT_THROTTLE_CLASSES」,它是用來經過配置文件settings來對全局節流類進行配置,功能等價於throttle_classes屬性變量。
5.‘DEFAULT_THROTTLE_RATES’從那裏來,有什麼用?
由SimpleRateThrottle類和上文對scope屬性變量的分析可知,DEFAULT_THROTTLE_RATES就是爲了存儲在配置文件中設置的不一樣的節流方法的。
綜上所述,能夠看出,在利用內置節流接口時,經過配置文件settings的設置和提供該接口所需的用戶惟一標識外,不須要咱們作再多的操做,這就造成了咱們上文寫的內置接口代碼基本結構的樣式。