三大认证-频率

自定义频率类

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=云边 先按价格降序 然后按名字过滤

image

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})
 posted on 2022-10-10 23:13  拾荒菇凉  阅读(68)  评论(0)    收藏  举报