1.DRF节流组件自定义(限制访问频率)   

 方式一 自定义类和方法:

  和上述的认证组件使用方式一样,定义一个频率组件类,推荐继承BaseThrottle类,

  需定义defallow_request(self,request,view):pass方法和defwait(self):pass提示信息方法

  

 seetings.py 

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
'rest_framework',
] MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
] REST_FRAMEWORK = {
#认证配置(全局配置)----针对所有的继承APIView的类,最终都会有结果返回
'DEFAULT_AUTHENTICATION_CLASSES' : ['app01.utils.auth.MyAuth',],#可以自定义多个认证类
# 'UNAUTHENTICATED_USER':lambda :'匿名用户request.user自定义值',#request.user有默认值
# 'UNAUTHENTICATED_TOKEN':lambda :'request.auth自定义值',#request.auth有默认值 #权限配置(全局配置)----针对所有的继承APIView的类,在认证之后执行,没有权限会返回message,有权限继续执行
'DEFAULT_PERMISSION_CLASSES':['app01.utils.permission.SVIPPermission',],#可以自定义多个权限 #频率配置(全局配置)----针对所有的继承APIView的类,在认证和权限校验之后
'DEFAULT_THROTTLE_CLASSES':['app01.utils.throttle.VisitThrottle',],#可以定义多个访问频率类
}

settings.py

  utils--auth.py--MyAuth认证类

#认证组件
from rest_framework.authentication import BaseAuthentication,BasicAuthentication class MyAuth(BaseAuthentication):#可以直接继承BaseAuthentication类,可以省略authenticate_header方法,或者继承BasicAuthentication
def authenticate(self, request):
token = request._request.GET.get('token')
token_obj = models.UserToken.objects.get(token=token)
if not token_obj:
raise exceptions.AuthenticationFailed('未认证用户!!!')
return (token_obj.user', 'request.auth') # 认证函数执行结果如果通过则为元组,元组第一个元素封装在为request.user

utils--auth.py--MyAuth认证类

  utils--permission.py--SVIPPermission/MyPermission权限类

from rest_framework.permissions import BasePermission

# 权限组件
class SVIPPermission(BasePermission):#推荐继承BasePermission类
# message = 'You do not have permission to perform this action.'#默认值
message = '无此权限!!!'
def has_permission(self,request, view):
if request.user.user_type == 3:
return False #False为没权限
return True #True为有权限 class MyPermission(BasePermission):#推荐继承BasePermission类
def has_permission(self,request, view):
if request.user.user_type != 3:
return False
return True

utils--permission.py--SVIPPermission/MyPermission权限类

  utils--throttle.py--VisitThrottle频率类

'''
访问频率一般存储在缓存或者数据库中,以往程序重启数据消失
再次示例使用字典存储,通过ip进行节流演示
'''
import time
from rest_framework.throttling import BaseThrottle # 节流组件
visit_record = {} # 设置访问频率5次/60s
TIME_LIMIT = 60
NUM_LIMIT = 5 # class VisitThrottle(object):
class VisitThrottle(BaseThrottle): # 推荐继承BaseThrottle类
'''
自定义频率组件类,推荐继承BaseThrottle类,
需定义 def allow_request(self, request, view):pass方法和def wait(self):pass提示信息方法
''' def __init__(self):
self.visit_history = [] def allow_request(self, request, view): # remote_addr = request.META.get('REMOTE_ADDR') # 获取客户端ip:request._request.META.get('REMOTE_ADDR')同样功能
remote_addr = self.get_ident(request) # 父类BaseThrottle中已经实现了此方法可以直接调用 visit_time = time.time()
if remote_addr not in visit_record: # 当前ip访问记录为空是第一次访问
visit_record[remote_addr] = [visit_time]
return True
else:
visit_history = visit_record.get(remote_addr)
while visit_history and (visit_time - visit_history[-1]) > TIME_LIMIT: # 访问记录存在并且最早时间记录与本次间隔大于限制时间就删除
visit_history.pop()
if len(visit_history) < NUM_LIMIT: # 当前访问记录次数与设定值比较,如果小于限定次数即可访问
visit_history.insert(0, visit_time)
return True
# 访问记录与本次访问时间封装在对象中以便wait调用
self.visit_history = visit_record.get(remote_addr)
self.visit_time = visit_time return False # False表示超次数 def wait(self):
'''
超出次数提示信息
:return: 提示信息:秒数 ''' return TIME_LIMIT - (self.visit_time - self.visit_history[-1])

utils--throttle.py--VisitThrottle频率类

  models.py

from django.db import models
# Create your models here
class UserInfo(models.Model):
"""
用户表
"""
user_type_choices = [
(1, '普通用户'),
(2, 'VIP用户'),
(3, 'SVIP用户'),
]
user_type = models.IntegerField(choices=user_type_choices)
username = models.CharField(max_length=10, unique=True)
password = models.CharField(max_length=12, null=False) class UserToken(models.Model):
"""
token表
""" user = models.OneToOneField(to='UserInfo')
token = models.CharField(max_length=64)
create_time = models.DateTimeField(auto_now=True) class Book(models.Model):
name = models.CharField(max_length=12)

models.py

  urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/v1/login/$', views.AuthView.as_view()),
url(r'^book/$', views.BookView.as_view(),name='book'),
url(r'^order/$', views.OrderView.as_view(),name='order'), ]

urls.py

  views.py

from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from app01 import models
from django.http import JsonResponse
from app01.utils.auth import MyAuth
from app01.utils.permission import MyPermission,SVIPPermission
from app01.utils.throttle import VisitThrottle
from django.views import View # Create your views here. # 实例url:http://127.0.0.1:8000/book/?token=1
class BookView(APIView):
# # (1)认证组件(局部使用)
# authentication_classes = [MyAuth, ]
#(2)权限组件(局部使用)
permission_classes = [MyPermission,]
# (3)频率组件(局部使用)
# throttle_classes = [VisitThrottle, ] def get(self, request):
print(request.user) # request.user在APIViewD的dispatch中进行封装的
return HttpResponse('GET') def post(self, request):
return HttpResponse('POST') def put(self, request):
return HttpResponse('PUT') def patch(self, request):
return HttpResponse('PATCH') def delete(self, request):
return HttpResponse('DELETE') class OrderView(APIView):
# (1)认证组件(局部使用)
# authentication_classes = [MyAuth, ]
# (2)权限组件(局部使用)
# permission_classes = [SVIPPermission]
#(3)频率组件(局部使用)
# throttle_classes = [VisitThrottle,] def get(self, request):
print(request.user) # request.user在认证组件中进行封装的
return HttpResponse('GET') def post(self, request):
return HttpResponse('POST') def put(self, request):
return HttpResponse('PUT') def patch(self, request):
return HttpResponse('PATCH') def delete(self, request):
return HttpResponse('DELETE') import time
import hashlib def token_md5(username):
"""
自定义token
:param username:
:return:
"""
t = time.time()
md5 = hashlib.md5(str(t).encode('utf-8'))
md5.update(username.encode('utf-8'))
return md5.hexdigest() class AuthView(View):
#如果不注册自定义组件,走默认的认证,最后返回了request.user和request.auth都是匿名用户默认值,可以在settings.py中加载自定义配置
#但是在权限认证时不不好处理,所以还是直接继承View
def post(self, request):
"""
用户登录
:param request:进行封装之后的request对象
:return: 登录结果信息
"""
ret = {'code': 0, 'msg': ''} username = request.POST.get('username', None)
password = request.POST.get('password', None) # 每次登陆如果有就更新没有就创建
try:
user_obj = models.UserInfo.objects.filter(username=username, password=password).first()
if user_obj:
token = token_md5(username)
print(token)
# 每次登陆如果有就更新没有就创建
models.UserToken.objects.update_or_create(user=user_obj, defaults={'token': token})
ret['msg'] = '登陆成功!'
ret['token'] = token
else:
ret['code'] = 1
ret['msg'] = '账号或密码有误!!!' except Exception as e:
ret['code'] = 2
ret['msg'] = '未知错误!!!'
finally:
return JsonResponse(ret)

views.py

2. DRF节流组件简单配置方式全局

  继承SimpleRateThrottle类可以直接进行简单配置即可,无需自己实现节流方法

  实现:scope和defget_cache_key(self,request,view):pass

  示例中的utils--throttle.py--VisitThrottle频率类方式二实现方式(结合settings.py配置)

  

  settings.py

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
'rest_framework',
] MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
REST_FRAMEWORK = {
#认证配置(全局配置)----针对所有的继承APIView的类,最终都会有结果返回(认证列表是或条件)
'DEFAULT_AUTHENTICATION_CLASSES' : ['app01.utils.auth.MyAuth',],#可以自定义多个认证类
# 'UNAUTHENTICATED_USER':lambda :'匿名用户request.user自定义值',#request.user有默认值
# 'UNAUTHENTICATED_TOKEN':lambda :'request.auth自定义值',#request.auth有默认值 #权限配置(全局配置)----针对所有的继承APIView的类,在认证之后执行,没有权限会返回message,有权限继续执行
'DEFAULT_PERMISSION_CLASSES':['app01.utils.permission.SVIPPermission',],#可以自定义多个权限 #频率配置(全局配置)----针对所有的继承APIView的类,在认证和权限校验之后(节流校验是并列的条件)
'DEFAULT_THROTTLE_CLASSES':['app01.utils.throttle.VisitThrottle','app01.utils.throttle.UserThrottle',],#可以定义多个访问频率类
'DEFAULT_THROTTLE_RATES':{ #继承节流组件的SimpleRateThrottle类使用
'ThrottleTest':'5/m',#该key是在自定义的组件类定义的,value值形如:'5/s'或者'5/seconds'均可(只要是以s,m,h,d即可)
#'LoginedUser':'10/m',#可以针对不懂得身份标识进行节流规则制定
}
}

settings.py

  utils--auth.py--MyAuth认证类

#认证组件
from rest_framework.authentication import BaseAuthentication,BasicAuthentication class MyAuth(BaseAuthentication):#可以直接继承BaseAuthentication类,可以省略authenticate_header方法,或者继承BasicAuthentication
def authenticate(self, request):
token = request._request.GET.get('token')
token_obj = models.UserToken.objects.get(token=token)
if not token_obj:
raise exceptions.AuthenticationFailed('未认证用户!!!')
return (token_obj.user', 'request.auth') # 认证函数执行结果如果通过则为元组,元组第一个元素封装在为request.user

utils--auth.py--MyAuth认证类

  utils--permission.py--SVIPPermission/MyPermission权限类

from rest_framework.permissions import BasePermission

# 权限组件
class SVIPPermission(BasePermission):#推荐继承BasePermission类
# message = 'You do not have permission to perform this action.'#默认值
message = '无此权限!!!'
def has_permission(self,request, view):
if request.user.user_type == 3:
return False #False为没权限
return True #True为有权限 class MyPermission(BasePermission):#推荐继承BasePermission类
def has_permission(self,request, view):
if request.user.user_type != 3:
return False
return True

utils--permission.py--SVIPPermission/MyPermission权限类

  utils--throttle.py--VisitThrottle频率类  

'''
访问频率一般存储在缓存或者数据库中,以往程序重启数据消失
再次示例使用字典存储,通过ip进行节流演示
'''
import time
from rest_framework.throttling import BaseThrottle, SimpleRateThrottle # 方式一节流组件(继承BaseThrottle类)----完全自定义写法
"""
visit_record = {} # 设置访问频率5次/60s
TIME_LIMIT = 60
NUM_LIMIT = 5 # class VisitThrottle(object):
class VisitThrottle(BaseThrottle): # 推荐继承BaseThrottle类
'''
自定义频率组件类,推荐继承BaseThrottle类,
需定义 def allow_request(self, request, view):pass方法和def wait(self):pass提示信息方法
''' def __init__(self):
self.visit_history = [] def allow_request(self, request, view): # remote_addr = request.META.get('REMOTE_ADDR') # 获取客户端ip:request._request.META.get('REMOTE_ADDR')同样功能
remote_addr = self.get_ident(request) # 父类BaseThrottle中已经实现了此方法可以直接调用 visit_time = time.time()
if remote_addr not in visit_record: # 当前ip访问记录为空是第一次访问
visit_record[remote_addr] = [visit_time]
return True
else:
visit_history = visit_record.get(remote_addr)
while visit_history and (visit_time - visit_history[-1]) > TIME_LIMIT: # 访问记录存在并且最早时间记录与本次间隔大于限制时间就删除
visit_history.pop()
if len(visit_history) < NUM_LIMIT: # 当前访问记录次数与设定值比较,如果小于限定次数即可访问
visit_history.insert(0, visit_time)
return True
# 访问记录与本次访问时间封装在对象中以便wait调用
self.visit_history = visit_record.get(remote_addr)
self.visit_time = visit_time return False # False表示超次数 def wait(self):
'''
超出次数提示信息
:return: 提示信息:秒数 ''' return TIME_LIMIT - (self.visit_time - self.visit_history[-1]) """ # 方式二节流组件(继承SimpleRateThrottle类)----需要在全局直接配置访问频率
# 该方式直接使用rest_framework自带的缓存机制,指定配置访问频率,还需重写def get_cache_key(self, request, view):pass返回用户访问身份标识key
class VisitThrottle(SimpleRateThrottle):
scope = 'ThrottleTest' # 继承SimpleRateThrottle类实现节流必须指定scope的值以便在全局配置使用 def get_cache_key(self, request, view):
return self.get_ident(request)#通过ip或代理进行节流 class UserThrottle(SimpleRateThrottle):
'''
本节流类以登录用户名为标识
'''
scope = 'LoginedUser' def get_cache_key(self, request, view):
return request.user#也可以通过用户名进行节流

utils--throttle.py--VisitThrottle频率类

  models.py  

from django.db import models
# Create your models here
class UserInfo(models.Model):
"""
用户表
"""
user_type_choices = [
(1, '普通用户'),
(2, 'VIP用户'),
(3, 'SVIP用户'),
]
user_type = models.IntegerField(choices=user_type_choices)
username = models.CharField(max_length=10, unique=True)
password = models.CharField(max_length=12, null=False) class UserToken(models.Model):
"""
token表
""" user = models.OneToOneField(to='UserInfo')
token = models.CharField(max_length=64)
create_time = models.DateTimeField(auto_now=True) class Book(models.Model):
name = models.CharField(max_length=12)

models.py

  urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/v1/login/$', views.AuthView.as_view()),
url(r'^book/$', views.BookView.as_view(),name='book'),
url(r'^order/$', views.OrderView.as_view(),name='order'), ]

urls.py

  views.py  

from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from app01 import models
from django.http import JsonResponse
from app01.utils.auth import MyAuth
from app01.utils.permission import MyPermission,SVIPPermission
from app01.utils.throttle import VisitThrottle
from django.views import View # Create your views here. # 实例url:http://127.0.0.1:8000/book/?token=1
class BookView(APIView):
# # (1)认证组件(局部使用)
# authentication_classes = [MyAuth, ]
#(2)权限组件(局部使用)
permission_classes = [MyPermission,]
# (3)频率组件(局部使用)
# throttle_classes = [VisitThrottle, ] def get(self, request):
print(request.user) # request.user在APIViewD的dispatch中进行封装的
return HttpResponse('GET') def post(self, request):
return HttpResponse('POST') def put(self, request):
return HttpResponse('PUT') def patch(self, request):
return HttpResponse('PATCH') def delete(self, request):
return HttpResponse('DELETE') class OrderView(APIView):
# (1)认证组件(局部使用)
# authentication_classes = [MyAuth, ]
# (2)权限组件(局部使用)
# permission_classes = [SVIPPermission]
#(3)频率组件(局部使用)
# throttle_classes = [VisitThrottle,] def get(self, request):
print(request.user) # request.user在认证组件中进行封装的
return HttpResponse('GET') def post(self, request):
return HttpResponse('POST') def put(self, request):
return HttpResponse('PUT') def patch(self, request):
return HttpResponse('PATCH') def delete(self, request):
return HttpResponse('DELETE') import time
import hashlib def token_md5(username):
"""
自定义token
:param username:
:return:
"""
t = time.time()
md5 = hashlib.md5(str(t).encode('utf-8'))
md5.update(username.encode('utf-8'))
return md5.hexdigest() class AuthView(View):
#如果不注册自定义组件,走默认的认证,最后返回了request.user和request.auth都是匿名用户默认值,可以在settings.py中加载自定义配置
#但是在权限认证是不好通过,所以还是直接继承View
def post(self, request):
"""
用户登录
:param request:进行封装之后的request对象
:return: 登录结果信息
"""
ret = {'code': 0, 'msg': ''} username = request.POST.get('username', None)
password = request.POST.get('password', None) # 每次登陆如果有就更新没有就创建
try:
user_obj = models.UserInfo.objects.filter(username=username, password=password).first()
if user_obj:
token = token_md5(username)
print(token)
# 每次登陆如果有就更新没有就创建
models.UserToken.objects.update_or_create(user=user_obj, defaults={'token': token})
ret['msg'] = '登陆成功!'
ret['token'] = token
else:
ret['code'] = 1
ret['msg'] = '账号或密码有误!!!' except Exception as e:
ret['code'] = 2
ret['msg'] = '未知错误!!!'
finally:
return JsonResponse(ret)

views.py

DRF节流组件的更多相关文章

  1. DRF版本组件

    1.DRF版本组件配置类局部使用 局部配置: 方式一:直接配置versioning_class=QueryParameterVersioning 方式二:直接配置versioning_class=UR ...

  2. python 全栈开发,Day97(Token 认证的来龙去脉,DRF认证,DRF权限,DRF节流)

    昨日内容回顾 1. 五个葫芦娃和三行代码 APIView(views.View) 1. 封装了Django的request - request.query_params --> 取URL中的参数 ...

  3. drf 频率组件 META字典详情

    drf频率组件 什么是频率 控制用户对某个url的请求频率,比如一分钟之内,只能访问三次 自定义频率规则 1.取出访问者ip 2.判断当前ip在不在访问字典中: 不在,则添加进去,返回True; 3. ...

  4. DRF之Jwt 实现自定义和DRF小组件及django-filter插件的使用

    一.DRF之Jwt 实现自定义 二.DRF(过滤,排序,分页)组件 三.Django-filter插件的使用和自定义 """ 1.drf-jwt手动签发与校验 :只是做t ...

  5. drf认证组件、权限组件、jwt认证、签发、jwt框架使用

    目录 一.注册接口 urls.py views.py serializers.py 二.登录接口 三.用户中心接口(权限校验) urls.py views.py serializers.py 四.图书 ...

  6. drf-jwt手动签发与校验,drf小组件:过滤、筛选、排序、分页

    复习 """ 频率组件:限制接口的访问频率 源码分析:初始化方法.判断是否有权限方法.计数等待时间方法 自定义频率组件: class MyThrottle(SimpleR ...

  7. DRF视图组件

    DRF视图组件: CVB模式继承----五层 from django.views import View # Django的View from rest_framework.views import ...

  8. DRF认证组件

    1.DRF认证组件之视图注册用法(自定义简单使用) settings.py配置 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.a ...

  9. DRF 视图组件

    目录 DRF 视图组件 视图组件大纲 两个视图基本类 五个扩展类 九个子类视图 视图集 常用视图集父类 魔法类 一览表 DRF中视图的"七十二变" 第一层:基于APIview的五个 ...

随机推荐

  1. weblogic补丁升级详细步骤,18.7.17补丁更新

    weblogic打补丁 到weblogic官网下载补丁包 对应的补丁包  如: p22248372_1036012_Generic.zip 一  安装补丁步骤 1.登录linux的weblogic用户 ...

  2. Spring Cloud sleuth with zipkin over RabbitMQ教程

    文章目录 Spring Cloud sleuth with zipkin over RabbitMQ demo zipkin server的搭建(基于mysql和rabbitMQ) 客户端环境的依赖 ...

  3. 【集群实战】Rsync数据同步工具

    1. Rsync介绍 1.1 什么是Rsync? Rsync是一款开源的,快速的,多功能的,可实现全量及增量的本地或远程数据同步备份的优秀工具.Rsync软件适用于unix/linux/windows ...

  4. 8.Python中装饰器是什么?

    Python中装饰器是什么? A Python decorator is a specific change that we make in Python syntax to alter functi ...

  5. 如何在Vue项目中优雅的使用swiper插件

    个人网站 https://iiter.cn 程序员导航站 开业啦,欢迎各位观众姥爷赏脸参观,如有意见或建议希望能够不吝赐教! 开始之前,请先确保有一个基于webpack模板的项目(vue-cli脚手架 ...

  6. centos6.5宽带拨号上网

    CentOS6以后要安装rp-pppoe这个软件,centos之前的版本是adsl-setup命令安装. (1)查看是否安装 #rpm -qa|grep rp-pppoe 没有内容输出则没安装,若可以 ...

  7. 疯子的算法总结(七) 字符串算法之 manacher 算法 O(N)解决回文串

    有点像DP的思想,写写就会做. #include<bits/stdc++.h> using namespace std; const int maxn=1e7+5; char a[maxn ...

  8. 一个简单的wed服务器SHTTPD(8)———— URI分析

    //start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191 ...

  9. nginx常见应用实例

    1.nginx 中 location 应用实例location 是 nginx 的精华,nginx 就是通过拦截到的请求去对配置好的 location 块(location block)进行请求代理的 ...

  10. Python解决钻石小偷问题

    题目如下: A:我没有偷钻石. B:D就是罪犯. C:B是盗窃这块钻石的罪犯. D:B有意诬陷我. 假定只有一个人说的是真话,编程序判断谁偷走了钻石. 答案是:说真话的是D,罪犯是A,逻辑思路可以百度 ...