一. REST framework的请求生命周期

基于rest-framework的请求处理,与常规的url配置不同,通常一个django的url请求对应一个视图函数,在使用rest-framework时,我们要基于视图对象,然后调用视图对象的as_view函数,as_view函数中会调用rest_framework/views.py中的dispatch函数,这个函数会根据request请求方法,去调用我们在view对象中定义的对应的方法,就像这样:
from app01 import views as app01_view

urlpatterns = [
url(r'^limits/', api_view.LimitView.as_view()),
]

二. 实例代码

1. 代码

from rest_framework.views import APIView
from rest_framework import exceptions
from rest_framework.response import Response
from rest_framework.throttling import SimpleRateThrottle class MySimpleRateThrottle(SimpleRateThrottle):
scope = "limit" def get_cache_key(self, request, view):
return self.get_ident(request) class LimitView(APIView):
authentication_classes = []
permission_classes = []
throttle_classes = [MySimpleRateThrottle, ] # 自定义分流类 def get(self, request, *args, **kwargs):
self.dispatch
return Response('控制访问频率示例') def throttled(self, request, wait): class MyThrottled(exceptions.Throttled):
default_detail = '请求被限制.'
extra_detail_singular = 'Expected available in {wait} second.'
extra_detail_plural = '还需要再等待{wait}' raise MyThrottled(wait)

2. 执行流程

    def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
# 1. 对request进行加工
# request封装了
"""
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
"""
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate? try:
# 初始化request
# 确定request版本,用户认证,权限控制,用户访问频率限制
self.initial(request, *args, **kwargs) # Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) except Exception as exc:
response = self.handle_exception(exc)
# 6. 二次加工request
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response

dispatch

    def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs) # Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg # Determine the API version, if versioning is in use.
# 2. 确定request版本信息
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted
# 3. 用户认证
self.perform_authentication(request)
# 4. 权限控制
self.check_permissions(request)
# 5. 用户访问频率限制
self.check_throttles(request)

initial

def check_throttles(self, request):
"""
Check if request should be throttled.
Raises an appropriate exception if the request is throttled.
"""
for throttle in self.get_throttles():
if not throttle.allow_request(request, self):
self.throttled(request, throttle.wait())

check_throttles

def get_throttles(self):
"""
Instantiates and returns the list of throttles that this view uses.
"""
return [throttle() for throttle in self.throttle_classes]

get_throttles

class APIView(View):

    # The following policies may be set at either globally, or per-view.
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
metadata_class = api_settings.DEFAULT_METADATA_CLASS
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS # Allow dependency injection of other settings to make testing easier.
settings = api_settings schema = DefaultSchema()

throttle_classes

3. 执行throttle中allow_request方法

def allow_request(self, request, view):
"""
Implement the check to see if the request should be throttled. On success calls `throttle_success`.
On failure calls `throttle_failure`.
"""
if self.rate is None:
return True self.key = self.get_cache_key(request, view)
if self.key is None:
return True self.history = self.cache.get(self.key, [])
self.now = self.timer() # Drop any requests from the history which have now passed the
# throttle duration
while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
if len(self.history) >= self.num_requests:
return self.throttle_failure()
return self.throttle_success()

自定义类继承SimpleRateThrottle

def get_cache_key(self, request, view):
"""
Should return a unique cache-key which can be used for throttling.
Must be overridden. May return `None` if the request should not be throttled.
"""
raise NotImplementedError('.get_cache_key() must be overridden')

get_cache_key

4. 处理报错异常

def throttled(self, request, wait):
"""
If request is throttled, determine what kind of exception to raise.
"""
raise exceptions.Throttled(wait)

throttled

class Throttled(APIException):
status_code = status.HTTP_429_TOO_MANY_REQUESTS
default_detail = _('Request was throttled.')
extra_detail_singular = 'Expected available in {wait} second.'
extra_detail_plural = 'Expected available in {wait} seconds.'
default_code = 'throttled' def __init__(self, wait=None, detail=None, code=None):
if detail is None:
detail = force_text(self.default_detail)
if wait is not None:
wait = math.ceil(wait)
detail = ' '.join((
detail,
force_text(ungettext(self.extra_detail_singular.format(wait=wait),
self.extra_detail_plural.format(wait=wait),
wait))))
self.wait = wait
super(Throttled, self).__init__(detail, code)

exceptions.Throttled

5. 重写throttled方法处理异常

def throttled(self, request, wait):

    class MyThrottled(exceptions.Throttled):
default_detail = '请求被限制.'
extra_detail_singular = 'Expected available in {wait} second.'
extra_detail_plural = '还需要再等待{wait}' raise MyThrottled(wait)

重写throttled方法

三. settings.py配置全局

1. 配置全局限流速度

REST_FRAMEWORK = {
'UNAUTHENTICATED_USER': None,
'UNAUTHENTICATED_TOKEN': None,
'DEFAULT_AUTHENTICATION_CLASSES': [ ],
'DEFAULT_PERMISSION_CLASSES': [], 'DEFAULT_THROTTLE_RATES': {
'anon': '5/minute',
'user': '10/minute',
'limit': '2/minute' # 设置每分钟访问次数 }
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': 'cache',
}
}

settings.py

2. 访问2次

3. 超过次数,提示报错

 

 
 
 
 
 
 

Django Rest Framework用户访问频率限制的更多相关文章

  1. Django rest framework 限制访问频率(源码分析)

    基于 http://www.cnblogs.com/ctztake/p/8419059.html 当用发出请求时 首先执行dispatch函数,当执行当第二部时: #2.处理版本信息 处理认证信息 处 ...

  2. Django中间件限制用户访问频率

    原:https://blog.csdn.net/weixin_38748717/article/details/79095399 一.定义限制访问频率的中间件 common/middleware.py ...

  3. django rest framework用户认证

    django rest framework用户认证 进入rest framework的Apiview @classmethod def as_view(cls, **initkwargs): &quo ...

  4. Django REST framework 内置访问频率控制

    对匿名用户采用 IP 控制访问频率,对登录用户采用 用户名 控制访问频率. from rest_framework.throttling import SimpleRateThrottle class ...

  5. Django Rest Framework 请求流程

    用户请求到django,首先经过wsgi,中间件,然后到url路由系统,执行视图类中继承APIView执行as_view方法,在源码中可以看到VPIView继承了django的View类,通过supe ...

  6. Django REST framework 之 认证 权限 限制

    认证是确定你是谁 权限是指你有没有访问这个接口的权限 限制主要是指限制你的访问频率 认证 REST framework 提供了一些开箱即用的身份验证方案,并且还允许你实现自定义方案. 接下类我们就自己 ...

  7. Django Rest Framework之用户频率/访问次数限制

    内置接口代码基本结构 settings.py: REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES':['api.utils.mythrottle.UserThr ...

  8. Django REST framework 自定义(认证、权限、访问频率)组件

    本篇随笔在 "Django REST framework 初识" 基础上扩展 一.认证组件 # models.py class Account(models.Model): &qu ...

  9. Django Rest Framework(认证、权限、限制访问频率)

    阅读原文Django Rest Framework(认证.权限.限制访问频率) django_rest_framework doc django_redis cache doc

随机推荐

  1. HDOJ.1010 Tempter of the Bone (DFS)

    Tempter of the Bone [从零开始DFS(1)] 从零开始DFS HDOJ.1342 Lotto [从零开始DFS(0)] - DFS思想与框架/双重DFS HDOJ.1010 Tem ...

  2. Bazinga 字符串HASH 这题不能裸HASH 要优化 毒瘤题

    Ladies and gentlemen, please sit up straight. Don't tilt your head. I'm serious. For nn given string ...

  3. ACM3371超时问题

    这的确也是个大坑: 其实在这是到很简单的最小生成树的题目,但是数据量却很大: 用G++提交会超时,用C++不会超时,而且速度超快: 又长见识了.可惜长得不是做题的能力,而是知道它到底有多坑. #inc ...

  4. JVM之字节码执行引擎

    方法调用: 方法调用不同于方法执行,方法调用阶段唯一任务就是确定被调用方法的版本(即调用哪一个方法),暂时还不执行方法内部的具体过程.方法调用有,解析调用,分派调用(有静态分派,动态分派). 方法解析 ...

  5. python基础--结构篇

    在C/C++/Java中,main是程序执行的起点,Python中,也有类似的运行机制,但方式却截然不同: Python使用缩进对齐组织代码的执行,所有没有缩进的代码(非函数定义和类定义),都会在载入 ...

  6. html 制作静态页面新知识

    1.在区块线边框添加一条水平线 例如:<div  style:"height :300px;width:800px;border-bottom: solid 1px orange ;& ...

  7. 【51NOD-0】1118 机器人走方格

    [算法]DP #include<cstdio> #include<algorithm> using namespace std; ,maxn=; int f[maxn][max ...

  8. 【SPOJ】2319 BIGSEQ - Sequence

    [算法]数位DP [题解]动态规划 题目要求的是大整数……没办法只写了小数字的,感觉应该没错. 大题框架是最大值最小化的二分问题. 对于每一块要求count(b)-count(a-1)≥s 已知a如何 ...

  9. bufferd对象详解

    使用buffer类处理二进制数据 在客户端javascript脚本代码中,对于二进制数据并没有提供一个很好的支持.然后在nodejs中需要处理像TCP流或文件流时,必须要处理二进制数据.因此在node ...

  10. Eureka Server的高可用

    Eureka Server进行互相注册的方式来实现高可用的部署,所以我们只需要将Eureke Server配置其他可用的serviceUrl就能实现高可用部署 创建application-peer1. ...