DRF Django REST framework 之 频率,响应器与分页器组件(六)
频率组件
频率组件类似于权限组件,它判断是否给予请求通过。频率指示临时状态,并用于控制客户端可以向API发出的请求的速率。
与权限一样,可以使用多个调节器。API可能会对未经身份验证的请求进行限制,而对于经过身份验证的请求则进行限制较少。
例如,可以将用户限制为每分钟最多60个请求,每天最多1000个请求。
自定义频率组件
使用方式与权限,认证组件几乎相同
该方式没有DRF提供的方式简洁
import time
import math from rest_framework import exceptions class MyException(exceptions.Throttled):
default_detail = '连接次数过多'
extra_detail_plural = extra_detail_singular = '请在{wait}秒内访问' def __init__(self, wait=None, detail=None, code=None):
super().__init__(wait=wait, detail=detail, code=code) class VisitThrottle():
user_visit_information = dict()
visited_times = 1
period = 60
allow_times_per_minute = 5
first_time_visit = True def allow_request(self, request, view):
self.request_host = request_host = request.META.get("REMOTE_ADDR")
current_user_info = self.user_visit_information.get(request_host, None) if not self.__class__.first_time_visit:
self.user_visit_information[request_host][0] += 1
current_visit_times = self.user_visit_information[request_host][0] if current_visit_times > self.allow_times_per_minute:
if self._current_time - current_user_info[1] <= self.period:
if len(current_user_info) > 2:
current_user_info[2] = self._time_left
else:
current_user_info.append(self._time_left) view.throttled = self.throttled
return None
else:
self.__class__.first_time_visit = True if self.first_time_visit:
self.__class__.first_time_visit = False
self._initial_infomation() return True def wait(self):
return self.period - self.user_visit_information[self.request_host][2] def throttled(self, request, wait):
raise MyException(wait=wait) @property
def _current_time(self):
return time.time() @property
def _time_left(self):
return math.floor(self._current_time - self.user_visit_information.get(self.request_host)[1]) def _initial_infomation(self):
self.user_visit_information[self.request_host] = [self.visited_times, self._current_time]
基于每个视图设置频率:
class BookView(ModelViewSet):# 指定频率类,固定写法
throttle_classes = [RateThrottle]
# 获取数据源, 固定写法
queryset = models.Book.objects.all()
# 序列化类, 固定写法
serializer_class = BookSerializer
使用DRF简单频率控制(局部)
from rest_framework.throttling import SimpleRateThrottle class RateThrottle(SimpleRateThrottle):
# 每分钟最多五次
rate = '5/m' def get_cache_key(self, request, view):
return self.get_ident(request)
rate代表访问评率,上面表示每分钟五次, get_cache_key 是必须存在的,它的返回值告诉当前频率控制组件要使用什么方式区分访问者(比如ip地址)。
在视图中使用:
class BookView(ModelViewSet):
# 指定频率类,固定写法
throttle_classes = [RateThrottle]
# 获取数据源, 固定写法
queryset = models.Book.objects.all()
# 序列化类, 固定写法
serializer_class = BookSerializer
全局频率控制
首先定义一个频率控制类,并且必须继承 SimpleRateThrottle 这个类,它是DRF提供的一个方便的频率控制类,请看下面的代码:
from rest_framework.throttling import SimpleRateThrottle class RateThrottle(SimpleRateThrottle):
scope = "visit_rate" def get_cache_key(self, request, view):
return self.get_ident(request)
在全局配置频率控制参数:
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES": ('app.utils.throttles.RateThrottle',),
"DEFAULT_THROTTLE_RATES": {
"visit_rate": "5/m"
}
}
这样就实现了,每分钟最多五次访问的逻辑。
另外,可以使用 DEFAULT_THROTTLE_CLASSES 和 DEFAULT_THROTTLE_RATES 设置全局设置默认的限制策略。
例如:
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
],
'DEFAULT_THROTTLE_RATES': {
# 游客每天访问次数不能超过100次
'anon': '100/day',
# 用户每天访问次数不能超过1000次
'user': '1000/day'
}
}
响应器
在使用DRF的Response类来将数据响应给客户端时,不管是POSTMAN工具还是浏览器,都能浏览到经过格式化后的,清晰易懂数据,DRF是怎么做的呢?其实就是通过响应器组件
响应器组件的使用
如果不需要使用DRF提供给浏览器的格式化后的数据,只需要禁止该响应方式即可:
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer class BookView(ModelViewSet):
# 指定响应器类,固定写法,返回json格式数据
renderer_classes = [JSONRenderer]
# 获取数据源, 固定写法
queryset = models.Book.objects.all()
# 序列化类, 固定写法
serializer_class = BookSerializer
这样,浏览器再次访问,接收到的就是普通的json格式数据,而不是经过DRF格式化后的数据,renderer_classes的查找逻辑与之前的解析器等等组件是完全一样的。
分页器
为了服务器性能考虑,也为了用户体验,我们不应该一次将所有的数据从数据库中查询出来,返回给客户端浏览器,如果数据量非常大,这对于服务器来讲,可以说是性能灾难,而对于用户来讲,加载速度将会非常慢。
而分页器能很好的解决该问题。
分页器的使用
第一步:导入模块
from rest_framework.pagination import PageNumberPagination
第二步:获取数据
books = Book.objects.all()
第三步:创建分页器
paginater = PageNumberPagination()
第四步:开始分页
paged_books = paginater.paginate_queryset(books, request)
第五步:将分页后的数据进行序列化
serialized_data = BookSerializer(paged_books, many=True)
第六步:返回数据
return Response(serialized_data.data)
常用参数介绍
常用分页器参数:
1. page_size: 用来控制每页显示多少条数据(全局参数名为PAGE_SIZE);
2. page_query_param: 用来提供直接访问某页的数据;
3. page_size_query_param: 临时调整当前显示多少条数据
4. max_page_size: 控制page_size_query_param参数能调整的最大条数 偏移分页器参数
1. default_limit: 每页显示的数据条数
2. offset_query_param: 要偏移的标杆,在前端以get的形式传,key为offset('可修改')
3. limit_query_param: 偏移量,在前端以get的形式传,key为limit('可修改')
4. max_limit: 一页最大的显示条数
自定义分页器
常用分页器 url :
# url:示例
http://http://127.0.0.1:8000/books/?page=2
# 在第二页显示,100条,但是page_size最大不能超过定义的max_page_size
http://http://127.0.0.1:8000/books/?page=2&page_size=100
常用分页器类:
from rest_framework.pagination import PageNumberPagination # 定义分页器类
class BookPageNumberPagination(PageNumberPagination):
# 默认一页条数
page_size = 2
# 前端发送的页数关键字名
page_query_param = 'page'
# 用户自定义一页条数 关键字名
page_size_query_param = 'page_size'
# 用户自定义一页最大控制条数
max_page_size = 2
偏移分页器 url :
# url:示例
http://http://127.0.0.1:8000/books/?limit=10
# 在100条后显示10条, 但是显示的条数不能超过定义的max_limit
http://http://127.0.0.1:8000/books/?limit=10&offset=100
偏移分页器类:
from rest_framework.pagination import LimitOffsetPagination class BookLimitOffsetPagination(LimitOffsetPagination):
# 默认一页条数
default_limit = 2
# 从offset开始往后显示limit条
limit_query_param = 'limit'
offset_query_param = 'offset'
# 最大显示多少条
max_limit = 4
视图类使用:
class BookView(ModelViewSet):
# 指定分页器类,固定写法,只能指定一个分页器类
pagination_class = BookPageNumberPagination
# pagination_class = BookLimitOffsetPagination
# 获取数据源, 固定写法
queryset = models.Book.objects.all()
# 序列化类, 固定写法
serializer_class = BookSerializer
~>.<~
DRF Django REST framework 之 频率,响应器与分页器组件(六)的更多相关文章
- 轻轻松松学会 DRF Django REST framework
据我了解,目前的IT行业的大部分后端开发,都是需要进行前后端分离的,而前后端分类必不可少的是rest 规范,以下是django rest framework的学习路径: DRF Django REST ...
- DRF Django REST framework APIView(一)
什么是REST? REST是一个标准,一种规范,遵循REST风格可以使开发的接口通用,便于调用者理解接口的作用. 使url更容易理解,让增删改清晰易懂,在前后端分离开发中按照这一规范能加快开发效率,减 ...
- [Django高级之批量插入数据、分页器组件]
[Django高级之批量插入数据.分页器组件] 批量插入数据 模板层models.py from django.db import models class Books(models.Model): ...
- Django REST Framework之频率限制
开放平台的API接口调用需要限制其频率,以节约服务器资源和避免恶意的频繁调用 使用 自定义频率限制组件:utils/thottle.py class MyThrottle(BaseThrottle): ...
- DRF Django REST framework 之 解析器(二)
引入 Django Rest framework帮助我们实现了处理application/json协议请求的数据,如果不使用DRF,直接从 request.body 里面拿到原始的客户端请求的字节数据 ...
- DRF (Django REST framework) 中的Request 与 Response
DRF中的Request 与 Response 1. Request - REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST f ...
- DRF Django REST framework 之 认证组件(五)
引言 很久很久以前,Web站点只是作为浏览服务器资源(数据)和其他资源的工具,甚少有什么用户交互之类的烦人的事情需要处理,所以,Web站点的开发这根本不关心什么人在什么时候访问了什么资源,不需要记录任 ...
- DRF (Django REST framework) 中的视图类
视图说明 1. 两个基类 1)APIView rest_framework.views.APIView APIView是REST framework提供的所有视图的基类,继承自Django的View父 ...
- DRF Django REST framework 之 序列化(三)
Django 原生 serializer (序列化) 导入模块 from django.core.serializers import serialize 获取queryset 对queryset进行 ...
随机推荐
- Mybatis动态SQL(where元素、set元素、if元素)
Mybatis动态SQL(where元素.set元素.if元素) - where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句.而且,若语句的开头为“AND”或 ...
- 领扣(LeetCode)单词模式 个人题解
给定一种 pattern(模式) 和一个字符串 str ,判断 str 是否遵循相同的模式. 这里的遵循指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向 ...
- mongodb存储二进制数据
mongodb 3.x存储二进制数据并不是以base64的方式,虽然在mongo客户端的查询结果以base64方式显示,请放心使用.下面来分析存储文件的存储内容.base64编码数据会增长1/3成为顾 ...
- PHP中Session ID的实现原理分析
ession 的工作机制: 为每个访问者创建一个唯一的 id (UID),并基于这个 UID 来存储变量.UID 存储在 cookie 中,亦或通过 URL 进行传导. PHPSESSIONID的生产 ...
- Java Import的使用
这里根据上一篇中ClassObject.java的例子改编的:https://www.cnblogs.com/jizizh/p/11938574.html 一.创建ClassObjectImport. ...
- 元数据管理的重要性 - xms
什么是元数据?引用百科的描述就是:元数据(Metadata),又称中介数据.中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息: 看起来有点抽象 ...
- java.lang.String 的 + 号操作到底做了什么事情?
前言 在之前的面试经历中,对于String的考察还是挺频繁的,大致考察以下几个知识点: String 常量池 new String() == 和 equals 的区别 native 方法 Strin ...
- Linux LVM 配置
本文出自 “www.kisspuppet.com” 博客,请务必保留此出处http://dreamfire.blog.51cto.com/418026/1084729 许多Linux使用者安装操作系统 ...
- Theano 更多示例
Logistic函数 logistic函数的图,其中x在x轴上,s(x)在y轴上. 如果你想对双精度矩阵上的每个元素计算这个函数,这表示你想将这个函数应用到矩阵的每个元素上. 嗯,你是这样做的: x= ...
- 关于HashMap容量的初始化,还有这么多学问。
在<HashMap中傻傻分不清楚的那些概念>文章中,我们介绍了HashMap中和容量相关的几个概念,简单介绍了一下HashMap的扩容机制. 文中我们提到,默认情况下HashMap的容量是 ...