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. Zookeeper之Error contacting service. It is probably not running.

    安装ZooKeeper时,无论是修改zoo.cfg:还是myid,都检查了几遍都没有错误.但是开启Zookeeper服务时出现: Error contacting service. It is pro ...

  2. 【Linux常见命令】uname命令

    uname命令用于显示系统信息. uname可显示电脑以及操作系统的相关信息. 语法 uname [-amnrsv][--help][--version] 参数说明: -a或--all 显示全部的信息 ...

  3. 09-5.部署 EFK 插件

    09-5.部署 EFK 插件 EFK 对应的目录:kubernetes/cluster/addons/fluentd-elasticsearch $ cd /opt/k8s/kubernetes/cl ...

  4. Flutter自己实现一个ProgressHUD

    用惯了iOS的SVProgressHUD,但是在flutter pub上的并没有找到类似的实现,于是自己实现一个 主要实现四个基本功能 Loading显示 成功显示 错误显示 进度显示:环形进度条和文 ...

  5. 怎样实现App安装来源追踪

    众所周知,国内的应用商店存在一定的限制,开发者很难有效监测到App安装来源的精准数据.但在实际推广中,广告效果.用户行为.付费统计.邀请关系等不同渠道的指标却是衡量渠道价值的关键,对App的运营推广和 ...

  6. pvresize

    lvm pv 扩容 pvresize 当PV对应的设备分区(如md软raid)扩容之后,利用该命令可以扩容PV

  7. flutter中使用redux之多界面互动

    在上一篇文章,我们介绍了如何在flutter中使用redux.在上一篇文章的例子中,我们使用了单界面集成redux,但是在实际项目中,我们通常涉及多个模块,每个模块涉及多个界面,那么如何使用redux ...

  8. jdbc连接mysql数据库 (idea)

    mysql我们已经不再陌生,但是通过Java来操作数据库的增删改查,我们就需要用到jdbc来连接: 我们使用idea来连接数据库,首先:我们电脑上需要安装idea和mysql,之后在网站上登录MySQ ...

  9. 练习//编写函数norepeat(arr) 将数组的重复元素去掉,并返回新的数组

    function norepeat(n){         for(var i=0;i<arr.length;i++){             for(var j=i+1;j<arr.l ...

  10. 工具类CountDownLatch的应用---百米赛跑案例

    package com.aj.thread; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Execu ...