python day72
从根上自定义频率类(了解)
class MyThrottling(BaseThrottle):
VISIT_RECORD = {} # 记录访问者的大字典
def __init__(self):
self.history = None
def allow_request(self, request, view):
# (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])
SimpleRateThrottle中写的和上面的本质上是一样的,只不过通过配置,可扩展性更高
过滤
内置过滤类的使用
1 在视图类中(必须继承GenericAPIView)
#配置过滤类
filter_backends=[SearchFilter,]
# 配置过滤字段
search_fields=['name','price']
2 浏览的地址:
查询的时候,所有条件都给search,并支持模糊匹配
http://127.0.0.1:8000/api/book/?search=红楼梦
http://127.0.0.1:8000/api/book/?search=水浒传
3 全局使用:在配置文件中配置
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
第三方过滤类使用(django-filter)
1 安装(支持django:2.2, 3.1, 3.2)
pip3 install django-filter
2 在视图类中(必须继承GenericAPIView) 写如下配置
#配置过滤类
filter_backends=[DjangoFilterBackend,]
# 配置过滤字段
filter_fields=['name','price']
3 浏览的地址:
http://127.0.0.1:8000/api/book/?price=30&name=红楼梦
http://127.0.0.1:8000/api/book/?price=30
4全局使用:在配置文件中配置
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
自己定义过滤类
1 写一个过滤类
from rest_framework.filters import BaseFilterBackend
class Myfilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
name = request.GET.get('name')
queryset = queryset.filter(name__contains=name)
return queryset
2 在视图类中配置
filter_backends = [Myfilter, ]
排序
1 在视图类中
filter_backends = [OrderingFilter, ]
ordering_fields=['price','name']
2 请求方式:
http://127.0.0.1:8000/api/book/?ordering=-price
http://127.0.0.1:8000/api/book/?ordering=price
http://127.0.0.1:8000/api/book/?ordering=-price,-name
异常处理
1 写一个函数
from rest_framework.response import Response
def my_exception_handler(exc, context):
response=exception_handler(exc, context)
print(response)
print(exc)
print(context.get('view'))
print(context.get('request').get_full_path())
if not response: #更新粒度的对异常做一个区分
if isinstance(exc,IndexError):
response=Response({'status':5001,'msg':'越界异常'})
elif isinstance(exc,ZeroDivisionError):
response = Response({'status': 5002, 'msg': '越界异常'})
else:
response= Response({'status': 5000, 'msg': '没有权限'})
# 这里可以记录日志
return response
2 在配置文件中配置
REST_FRAMEWORK = {
'EXCEPTION_HANDLER':'app01.excepiton.my_exception_handler'
}
3 只要以后视图函数中出了错误,都会返回统一格式