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. UML由浅入深

    在UML 2.0的13种图形中,类图是使用频率最高的UML图之一.Martin Fowler在其著作<UML Distilled: A Brief Guide to the Standard O ...

  2. Ubuntu parted 命令 写在脚本里时要带 -s 参数

    否则会要求用户输入,造成脚本卡住.

  3. [Qt] 打开Diskmgmt

    QProcess mOpenDiskMgmt; QString program = "cmd"; QStringList arguments; arguments << ...

  4. Spring Boot中的Properties

    文章目录 简介 使用注解注册一个Properties文件 使用属性文件 Spring Boot中的属性文件 @ConfigurationProperties yaml文件 Properties环境变量 ...

  5. 【java基础】01 计算机基础知识

    一.计算机基础知识 1. 计算机 1. 什么是计算机? 计算机在生活中的应用举例 计算机(Computer)全称:电子计算机,俗称电脑.是一种能够按照程序运行,自动.高速处理海量数据的现代化智能电子设 ...

  6. RequestDispatcher.forward() 方法和HttpServletResponse.sendRedirect()方法的区别

    RequestDispatcher.forward() 方法和HttpServletResponse.sendRedirect()方法的区别 先贴一段代码 public void logon(Http ...

  7. STL--priority_queue--自定义数据类型

    STL中priority_queue的声明模板有3个参数priority_queue<Type,Container,Functional>. 当使用的数据类型Type为自定义数据类型时有以 ...

  8. CF思维联系– Codeforces-988C Equal Sums (哈希)

    ACM思维题训练集合 You are given k sequences of integers. The length of the i-th sequence equals to ni. You ...

  9. Codeforce 1251C. Minimize The Integer

    C. Minimize The Integer time limit per test2 seconds memory limit per test256 megabytes inputstandar ...

  10. codeforce 266c Below the Diagonal 矩阵变换 (思维题)

    C. Below the Diagonal You are given a square matrix consisting of n rows and n columns. We assume th ...