Django Rest Framework用户访问频率限制
一. REST framework的请求生命周期
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用户访问频率限制的更多相关文章
- Django rest framework 限制访问频率(源码分析)
基于 http://www.cnblogs.com/ctztake/p/8419059.html 当用发出请求时 首先执行dispatch函数,当执行当第二部时: #2.处理版本信息 处理认证信息 处 ...
- Django中间件限制用户访问频率
原:https://blog.csdn.net/weixin_38748717/article/details/79095399 一.定义限制访问频率的中间件 common/middleware.py ...
- django rest framework用户认证
django rest framework用户认证 进入rest framework的Apiview @classmethod def as_view(cls, **initkwargs): &quo ...
- Django REST framework 内置访问频率控制
对匿名用户采用 IP 控制访问频率,对登录用户采用 用户名 控制访问频率. from rest_framework.throttling import SimpleRateThrottle class ...
- Django Rest Framework 请求流程
用户请求到django,首先经过wsgi,中间件,然后到url路由系统,执行视图类中继承APIView执行as_view方法,在源码中可以看到VPIView继承了django的View类,通过supe ...
- Django REST framework 之 认证 权限 限制
认证是确定你是谁 权限是指你有没有访问这个接口的权限 限制主要是指限制你的访问频率 认证 REST framework 提供了一些开箱即用的身份验证方案,并且还允许你实现自定义方案. 接下类我们就自己 ...
- Django Rest Framework之用户频率/访问次数限制
内置接口代码基本结构 settings.py: REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES':['api.utils.mythrottle.UserThr ...
- Django REST framework 自定义(认证、权限、访问频率)组件
本篇随笔在 "Django REST framework 初识" 基础上扩展 一.认证组件 # models.py class Account(models.Model): &qu ...
- Django Rest Framework(认证、权限、限制访问频率)
阅读原文Django Rest Framework(认证.权限.限制访问频率) django_rest_framework doc django_redis cache doc
随机推荐
- vue-router的钩子
vue-router的钩子分为三类: 1. 全局钩子2. 路由独享钩子3. 组件内钩子 1. 全局钩子 beforeEach(to,from,next) afterEach(route) 2. 路由独 ...
- linux上修改系统默认语言设置
locale命令设置语言环境(临时修改) [keysystem@localhost ~]$ date Fri Feb :: CST [keysystem@localhost ~]$ locale LA ...
- [存一下]iptables模块
介绍地址: http://www.tummy.com/blogs/2005/07/17/some-iptables-modules-you-probably-dont-know-about/ [1] ...
- eclipse ----- indexer
使能indexer,可以实现变量.函数等的跳转, 即跳转到定义的位置
- [解决] Error Code: 1044. Access denied for user 'root'@'%' to database
今天在测试集群用的mysql上,遇到个权限的问题: SQLException : SQL state: 42000 com.mysql.jdbc.exceptions.jdbc4.MySQLSynta ...
- Iterator与ListIterator的区别
Iterator与ListIterator 相同点:(1)两者都是fail-fast机制,都是作为内部类实现的. 区别:二者的区别主要是功能上的: (1)Iterator实现了接口Iterator,属 ...
- MyBatis框架的使用及源码分析(三) 配置篇 Configuration
从上文<MyBatis框架中Mapper映射配置的使用及原理解析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder> 我们知道XMLConf ...
- Jenkenis报错:该jenkins实例似乎已离线[转]
解决方法: 安装插件那个页面,就是提示你offline的那个页面,不要动.然后打开一个新的tab,输入网址http://localhost:8080/pluginManager/advanced. 这 ...
- wiki文档书写格式
文档基本规范 标题 标题:标明需求的简短语句.或模块名称,目录是由标题生成,一份目录结构清晰的需求文档与标题的划分是密不可分. 正文 正文:有规范格式和生效标志的正式文本,正文包括 文字.表格.图片. ...
- 「6月雅礼集训 2017 Day7」电报
[题目大意] 有n个岛屿,第i个岛屿有有向发射站到第$p_i$个岛屿,改变到任意其他岛屿需要花费$c_i$的代价,求使得所有岛屿直接或间接联通的最小代价. $1 \leq n \leq 10^5, 1 ...