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的设置和提供该接口所需的用户惟一标识外,不须要咱们作再多的操做,这就造成了咱们上文写的内置接口代码基本结构的样式。