三大认证-频率
自定义频率类
from rest_framework.throttling import BaseThrottle
import time
class UserThorttle(BaseThrottle):
VISIT_RECORD = {}
def __init__(self):
self.history = None
def allow_request(self, request, view):
ip = request.META.get('REMOTE_ADDR')
nowtime = time.time()
if ip not in self.VISIT_RECORD:
self.VISIT_RECORD[ip] = [nowtime, ]
return True
self.history = self.VISIT_RECORD.get(ip)
while self.history and nowtime-self.history[-1] > 60:
self.history.pop()
if len(self.history) < 3:
self.history.insert(0, nowtime)
return True
return False
频率源码分析
1.SimpleRateThrottle重写allow_request方法
2.判断self.rate是否为空--self.rate--时间列表
3.通过反射区获取rate 获取self.history时间列表
4.获取当前时间
5.通过循环判断列表中的最早的时间与当前时间的差额是否大于60,大于删除最早的时间
6.判断列表中的时间个数是否大于self.num_requests=5
7.大于返回False 小于返回True
def allow_request(self, request, view):
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()
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()
2.实例化时通过反射获取rate--执行get_rate
获取到rate执行self.parse_rate(self.rate)
获取返回的值self.num_requests=5, self.duration=60
def __init__(self):
if not getattr(self, 'rate', None):
self.rate = self.get_rate()
self.num_requests, self.duration = self.parse_rate(self.rate)
3.通过反射获取scope--我们自己写的频率限制
所以在继承SimpleRateThrottle需要写一个scope类属性 并在配置文件中配置频率限制
def get_rate(self):
if not getattr(self, 'scope', None):
raise ImproperlyConfigured(msg)
try:
return self.THROTTLE_RATES[self.scope]
except KeyError:
raise ImproperlyConfigured(msg)
4.执行self.parse_rate(self.rate)
将{'user_throttle': '5/m'}
将字符串'5/m'通过/分割并通过解压赋值num='5' period='m'
将字符串num='5'转为整数5给到num_requests=5
通过索引拿到period的第一个字符串并通过字典取值获取对应的时间duration=60
返回num_requests=5,duration=60
def parse_rate(self, rate):
if rate is None:
return (None, None)
num, period = rate.split('/')
num_requests = int(num)
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
return (num_requests, duration)
分页
1.必须是继承GenericAPIView+ListModelMixin的子视图类上
1.方式一
from rest_framework.pagination import CursorPagination
class BookPage(CursorPagination):
cursor_query_param = 'cursor'
page_size = 2
ordering = 'price'
2.方式二
from rest_framework.pagination import PageNumberPagination
class BookPage(PageNumberPagination):
page_size = 2
page_query_param = 'page'
page_size_query_param = 5
max_page_size = 5
3.方式三
from rest_framework.pagination import LimitOffsetPagination
class BookPage(LimitOffsetPagination):
default_limit = 2
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 5
视图类中导入
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
pagination_class = BookPage
注:1.写一个分页类
2.继承CursorPagination、PageNumberPagination、LimitOffsetPagination中的一个
3.写类属性
CursorPagination:
排序
1.必须是继承GenericAPIView+ListModelMixin的子视图类上
2.路径:http://127.0.0.1:8000/books/?ordering=price
1.from rest_framework.filters import OrderingFilter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [OrderingFilter, ]
ordering_fields = ['price', ]
注:1.继承OrderingFilter排序类
2.局部导入:filter_backends = [OrderingFilter, ]
3.排序字段:ordering_fields = ['price', ]
过滤
1.必须是继承GenericAPIView+ListModelMixin的子视图类上
2.路径:http://127.0.0.1:8000/books/?search=救赎
1.from rest_framework.filters import SearchFilter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [SearchFilter, ]
search_fields = ['name', 'publish']
注:继承过滤类SearchFilter
局部导入:filter_backends = [SearchFilter, ]
过滤字段:search_fields = ['name', 'publish'] 如果是多个字段之间是或的关系
作业
1 带排序,带按名字过滤
1.视图类:
from rest_framework.filters import OrderingFilter, SearchFilter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [OrderingFilter, SearchFilter]
ordering_fields = ['price', ]
search_fields = ['name', ]
2.网址:
http://127.0.0.1:8000/books/?ordering=-price&search=云边 先按价格降序 然后按名字过滤
2 继承APIView,实现分页,返回格式跟之前一样
class BookView1(APIView):
def get(self, request):
book_list = Book.objects.all()
page = BookPage()
res = page.paginate_queryset(book_list, request)
book_obj = BookSerializer(instance=res, many=True)
count = len(book_list)
url = request.path
path = request.META.get('REMOTE_ADDR')+url
previous = request.query_params.get('offset')
return Response({'count': count, 'next': path, 'previous': previous, 'results': book_obj.data})
标签:return,08,request,self,rate,num,class,drf
From: https://www.cnblogs.com/040714zq/p/16777816.html