首页 |  我的博客 |  查看该博主内容分类 | 

django限流

pip install django-redis

1. seetings配置

CACHES = {
    'default': {
		'BACKEND': 'django_redis.cache.RedisCache',
		'LOCATION': 'redis://127.0.0.1:6379',
		'OPTIONS': {
			'CLIENT_CLASS': 'django_redis.client.DefaultClient',
			# 'CONNECTION_POOL_KWARGS': {'max_connections': 100},  # 最大连接数,可选
			'PASSWORD': '123456'
		}
	}
}

2. 编写限流类

from django.core.cache import cache as default_cache
from rest_framework import exceptions


class ThrottleException(exceptions.APIException):
    # status_code = status.HTTP_429_TOO_MANY_REQUESTS
    # default_code = 'throttle'
    # 上述不写也可以
    pass

class MyRateThrottle(SimpleRateThrottle):
    # cache = default_cache  # 访问记录存放在django的缓存中,默认为这个,可不写
    scope = 'user'  # 用来构造缓存中的key,可任意字符串
    THROTTLE_RATES = {'user': '10/m'}  # user:缓存的key,也就是scope;s秒,m分,h小时,d天,10/m十次每分钟
    
    def get_cache_key(self, request, view):  # 返回用户标识
        # 判断登录和未登录情况逻辑
        if request.user:
            ident = request.user.pk  # 用户ID
        else:
            ident = self.get_ident(request)  # 获取请求用户IP(去request找请求头)
        return f'throttle_{self.scope}_{ident}'
    
    def throttle_failure(self):  # 限流时返回的信息,原带简易版
        wait = self.wait()  # 需要等待的时间
        detail = {
            'code': 1005,
            'data': '访问频率限制',
            'detail': f'需等待{int(wait)}s才能访问',
        }
        # 如果ThrottleException内容是pass,可以改写成exceptions.APIException(detail)
        raise ThrottleException(detail)

3. 使用

# 视图类中使用
throttle_classes = [MyRateThrottle, ...]

4. 多个限流类

throttle_failure(self) 返回True继续,False超频但还会继续后续的限流类,所有限流类执行完毕后,求和所有返回False的等待时间
raise xxx:超出频率,抛出异常,将停止后续的执行。

可在视图类中设置多个限流类后的限流函数:

class View(xxx):
    ...
	def throttle(self, request, wait):
        detail = {
            'code': 1005,
            'data': '访问频率限制',
            'detail': f'需等待{int(wait)}s才能访问',
    	}
        raise ThrottleException(detail)

5. 全局配置

rest_framework = {
    'DEFAULT_THROTTLE_CLASSES': ['限流类1路径', '限流类2路径', '限流类3路径', ...],
    'DEFAULT_THROTTLE_RATES': {
        'user': '10/m',  # 可省略限流类THROTTLE_RATES的指定,可为某一类事件做固定频率的限制
        'xxx': '20/m',
        ...
    }
}
posted @ 2022-09-20 17:05  Z哎呀  阅读(123)  评论(0编辑  收藏  举报
// let homeEle = document.querySelector('body') // homeEle.setAttribute('id', 'particles-js') // /* ---- particles.js config ---- */ // particlesJS("particles-js", { // "particles": { // "number": { // "value": 380, // "density": { // "enable": true, // "value_area": 800 // } // }, // "color": { // "value": "#ffffff" // }, // "shape": { // "type": "circle", // "stroke": { // "width": 0, // "color": "#000000" // }, // "polygon": { // "nb_sides": 5 // }, // "image": { // "src": "img/github.svg", // "width": 100, // "height": 100 // } // }, // "opacity": { // "value": 0.5, // "random": false, // "anim": { // "enable": false, // "speed": 1, // "opacity_min": 0.1, // "sync": false // } // }, // "size": { // "value": 3, // "random": true, // "anim": { // "enable": false, // "speed": 40, // "size_min": 0.1, // "sync": false // } // }, // "line_linked": { // "enable": true, // "distance": 150, // "color": "#ffffff", // "opacity": 0.4, // "width": 1 // }, // "move": { // "enable": true, // "speed": 6, // "direction": "none", // "random": false, // "straight": false, // "out_mode": "out", // "bounce": false, // "attract": { // "enable": false, // "rotateX": 600, // "rotateY": 1200 // } // } // }, // "interactivity": { // "detect_on": "canvas", // "events": { // "onhover": { // "enable": true, // "mode": "grab" // }, // "onclick": { // "enable": true, // "mode": "push" // }, // "resize": true // }, // "modes": { // "grab": { // "distance": 140, // "line_linked": { // "opacity": 1 // } // }, // "bubble": { // "distance": 400, // "size": 40, // "duration": 2, // "opacity": 8, // "speed": 3 // }, // "repulse": { // "distance": 200, // "duration": 0.4 // }, // "push": { // "particles_nb": 4 // }, // "remove": { // "particles_nb": 2 // } // } // }, // "retina_detect": true // }); // var count_particles, stats, update; // stats = new Stats; // stats.setMode(0); // stats.domElement.style.position = 'absolute'; // stats.domElement.style.left = '0px'; // stats.domElement.style.top = '0px'; // document.body.appendChild(stats.domElement); // count_particles = document.querySelector('.js-count-particles'); // update = function() { // stats.begin(); // stats.end(); // if (window.pJSDom[0].pJS.particles && window.pJSDom[0].pJS.particles.array) { // count_particles.innerText = window.pJSDom[0].pJS.particles.array.length; // } // requestAnimationFrame(update); // }; // requestAnimationFrame(update);