整理了几个版本的,经过测试目前正常.....

第一版:

第一版和第三版引用方式不同,第三版是在视图类里面,第一版是在配置文件引用.

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'throttle.service.throttle_class.VisitThrottle',
    ),
}

 

第二版:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# Python
import time
# Third-party Library
from rest_framework.throttling import BaseThrottle
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)

# 访问记录
VISITED_RECORD = {}


class VisitThrottle(BaseThrottle):
    def __init__(self):
        self.history = None
        self.ctime = time.time()
        self.period = 60
        self.visit_ip = None

    # 访问限制方法
    def allow_request(self, request, view):
        visit_ip = self.get_ident(request)
        self.visit_ip = visit_ip
        # visit_ip=request.META.get('REMOTE_ADDR')
        print(visit_ip)


        # 第一次访问请求
        if visit_ip not in VISITED_RECORD:
            VISITED_RECORD[visit_ip] = [self.ctime]
            return True
        # self.history:当前请求IP的记录列表
        self.history = VISITED_RECORD[visit_ip]
        print(self.history)

        # 第2,3,...次访问请求
        if len(VISITED_RECORD[visit_ip]) < 3:
            VISITED_RECORD[visit_ip].insert(0, self.ctime)
            return True

        if self.ctime - VISITED_RECORD[visit_ip][-1] > self.period:
            VISITED_RECORD[visit_ip].pop()
            VISITED_RECORD[visit_ip].insert(0, self.ctime)
            return True
        view.throttled = self.throttled
        return False

    def wait(self):
        return self.ctime - VISITED_RECORD[self.visit_ip][-1]

    def throttled(self, request, wait):
        raise MyException(wait=wait)

 

第三版:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
功能:限制用户访问频率
"""
# Django Library
import time, math
# Third-party Library
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]

如何使用上面的代码限制频率

打开你的视图文件,一般是views.py,如果你把文件修改名字了,那么就放在你修改你后的文件里.

# 导入频率组件,也就是上面的文件
from app01.service.throttle import VisitThrottle

# 图书视图类
class BookView(ModelViewSet):
    # 频率限制
    throttle_classes = [VisitThrottle]
    # 获取图书列表
    queryset = Book.objects.all()
    # 序列化类
    serializer_class = BookSerializer

'''
注意:
因为之前写过认证组件和权限组件了,这里只写和频率认证组件有关的代码,就不重复粘代码.
可以去上一篇把代码粘过来.
https://www.cnblogs.com/apollo1616/articles/10100264.html
'''