yaya

今天也要加油鸭!!!

频率认证

 shell环境

 迁移数据之后,可以在shell环境中做测试😘
 在这个环境下可以快速的修改一些数据😘

频率简介

为了控制用户对某个url请求的频率,比如,一分钟以内,只能访问三次

 自定义频率类,自定义频率规则

1.在settings中配置   INSTALLED_APPS=['rest_framework']

2.settings中配置  

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES':{
'luffy':'3/m'
#scope='lxx',表示一分钟访问三次
}
}

3.models.py

from django.db import models

# Create your models here.
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField(null=True)
    xx=models.IntegerField(choices=((0,'文学类'),(1,'情感类')),default=1,null=True)
    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE,null=True)
    authors=models.ManyToManyField(to='Author')
    def __str__(self):
        return self.name
    def test(self):
        return 'xxx'


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()



class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

    def __str__(self):
        return self.name
View Code

注意:数据迁移

4.urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'books/', views.Books.as_view())
]
View Code

5.views.py

from django.shortcuts import render

# Create your views here.

from rest_framework.views import APIView

from rest_framework.response import Response
from rest_framework.throttling import SimpleRateThrottle,BaseThrottle
#第一步,写一个频率类,继承SimpleRateThrottle
    #重写get_cache_key, 返回self.get_ident(request)
    #一定要记住配置一个scope字符串
#第二步:在settings中配置

#频率的一个类
class Throttle(SimpleRateThrottle):
    scope='lxx'
    def get_cache_key(self, request, view):
        return self.get_ident(request)



class Books(APIView):

    throttle_classes = []
    def get(self, request):
        return Response('')

编写自定义的类

from django.shortcuts import render

# Create your views here.

from rest_framework.views import APIView

from rest_framework.response import Response
from rest_framework.throttling import SimpleRateThrottle,BaseThrottle
#第一步,写一个频率类,继承SimpleRateThrottle
    #重写get_cache_key, 返回self.get_ident(request)
    #一定要记住配置一个scope字符串
#第二步:在settings中配置

#频率的一个类
class Throttle(SimpleRateThrottle):
    scope='lxx'
    def get_cache_key(self, request, view):
        return self.get_ident(request)

#自定义频率类
class MyThrottle(BaseThrottle):
    VISIT_RECORD = {}

    def __init__(self):
        self.history = None
    def allow_request(self, request, view):
        #自定义控制每分钟访问多少次,允许访问返回true,不允许访问返回false
        # (1)取出访问者ip
        # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
        # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
        # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
        # (1)取出访问者ip
        # print(request.META)
        ip = request.META.get('REMOTE_ADDR')
        import time
        ctime = time.time()
        # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问
        if ip not in self.VISIT_RECORD:
            self.VISIT_RECORD[ip] = [ctime, ]
            return True
        self.history = self.VISIT_RECORD.get(ip)
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
        while self.history and ctime - self.history[-1] > 60:
            self.history.pop()
        # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
        # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
        if len(self.history) < 3:
            self.history.insert(0, ctime)
            return True
        else:
            return False
    def wait(self):
        import time
        ctime = time.time()
        return 60 - (ctime - self.history[-1])


class Books(APIView):

    throttle_classes = []
    def get(self, request):
        return Response('')
View Code

自定义的逻辑

#(1)取出访问者ip
# (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
# (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
# (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
# (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败

 

以下是源码(跟我们自定义的逻辑一样,也是要重写allow_request方法)分析:😁

-SimpleRateThrottle源码🎇

点击SimpleRateThrottle进入到类中,找到allow_request方法

补充:这个访问者ip是存放入缓存当中,而在自定义的逻辑中的是保存在字典中,这里的reqeust.META.get('REMOTE_ADDR')只是暂时的获取到ip,后面要改为

self.get_ident(request)

 
首先先走的是if self.rate is None:如果为空就返回True,但是不可能为空
重写了get_cache_key,它返回什么就以什么做过滤
 

然后在缓存里根据ip地址取出时间列表

获取当前时间

 

判断当前时间是否为空,并且取出最后一个值是否大于我配置的时间,当前时间减去我配置时间进行做比较,如果是就把最后的时间pop,再判断长度是否大于我配置的3,大于3不能访问,小于3可以访问

以上总结:不需要写allow_reqeust的方法的,只需要重写获取ip的get_cache_key的方法

在__init__返回rate,这个rate就是3/m

然后把3/m传入parse_rate中

再读parse_rate,通过斜杆切分再解压,period[0]字符串取第0个值,如果period=m,现在duration=60,返回3 和60,这些值就可以动态获取

SimpleRateThrottle中的父类中有BaseThrottle才有,返回访问者的ip

返回什么值就以什么来过滤,返回ip就以ip做过滤,返回用户的id就以用户的id做过滤

 

posted @ 2019-07-04 20:08  Tiffany'.'  阅读(169)  评论(0编辑  收藏  举报