一、rest-framework之频率控制
为了控制用户对某个url请求的频率,比如,一分钟以内,只能访问三次
1)自定义模式,其他框架调使用也是如此
自定义频率逻辑
# (1)取出访问者ip # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走 # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间, # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过 # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
代码实现
class MyThro(): VISIT_RECORD = {} def __init__(self): self.history=None def allow_request(self,request, view): #(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])
视图函数引用组件
from app01.auth import MyThro class Book(APIView): authentication_classes = [myAuthen,] # 认证 permission_classes = [myPermission,] # 权限 throttle_classes = [MyThro,] # 频率 def get(self,request): response = MyResponse() # print(request.user.name) # 打印用户 # print(request.auth.token) # 携带的token books=models.Book.objects.all() ret = myserial.BookSer(instance=books,many=True) response.msg = '查询成功' response.data=ret.data return JsonResponse(response.get_dic,safe=False)
2)引用resful的方式
创建频率组件
from rest_framework.throttling import SimpleRateThrottle class MyThro(SimpleRateThrottle): scope = 'aaa' def get_cache_key(self, request, view): # return self.get_ident(request) # 第一种写法 return request.META.get('REMOTE_ADDR') # 第二种写法
视图函数
from app01 import myserial from app01.auth import myPermission from app01.auth import MyThro class Book(APIView): authentication_classes = [myAuthen,] # 认证 permission_classes = [myPermission,] # 权限 throttle_classes = [MyThro,] # 频率 def get(self,request): response = MyResponse() # print(request.user.name) # 打印用户 # print(request.auth.token) # 携带的token books=models.Book.objects.all() ret = myserial.BookSer(instance=books,many=True) response.msg = '查询成功' response.data=ret.data return JsonResponse(response.get_dic,safe=False)
2.1)如果是全局使用
REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES':[ 'rest_framework.parsers.JSONParser' # 解析器 ], "DEFAULT_AUTHENTICATION_CLASSES":["app01.auth.myAuthen",], # 认证组件 "DEFAULT_PERMISSION_CLASSES": ["app01.auth.myPermission", ], # 权限组件 "DEFAULT_THROTTLE_RATES":{ 'aaa':'1/m' # 频率组件 }, }
2.2)访问时间参数
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]] 源码内容 s ==> 秒 m ==> 分 h ==> 时 d ==> 天
2.3)小结
-定义一个类: from rest_framework.throttling import SimpleRateThrottle class MyThro(SimpleRateThrottle): scope = 'aaa' def get_cache_key(self, request, view): # return self.get_ident(request) return request.META.get('REMOTE_ADDR') -setting中配置 "DEFAULT_THROTTLE_RATES":{ 'aaa':'3/m' } -全局使用: 'DEFAULT_THROTTLE_CLASSES':['app01.auth.MyThro',], -局部使用: throttle_classes=[MyThro,]
二、rest-framework之分页
1)简单分页:from rest_framework.pagination import PageNumberPagination
from app01 import myserial # 序列化 from app01.auth import myPermission from app01.auth import MyThro from rest_framework.pagination import PageNumberPagination # 分页 class Book(APIView): authentication_classes = [myAuthen,] # 认证 permission_classes = [myPermission,] # 权限 throttle_classes = [MyThro,] # 频率 print('ok') def get(self,request): response = MyResponse() books=models.Book.objects.all() page = PageNumberPagination() page.page_size=2 # 定义默认显示每页显示的条数 page.page_query_param='dasb' # 定义页面的名字 # 如 http://127.0.0.1:8000/books/?dasb=2&token=1d64b50ea99db6b66ab379dcfbfc5814 # dasb的第二页 # page.page_query_param='dasb' # 不写默认是page page.page_size_query_param='max' # 显示条数,可覆盖 page.page_size=2 # 如http://127.0.0.1:8000/books/?dasb=2&max=3&token=1d64b50ea99db6b66ab379dcfbfc5814 page.max_page_size=3 # 控制 page.page_size_query_param='max' 定义参数的最大值,超出了,也显示这里定义的3条数据 page_book = page.paginate_queryset(books,request,view=self) ret = myserial.BookSer(instance=page_book,many=True) response.msg = '查询成功' response.data=ret.data return JsonResponse(response.get_dic,safe=False)
1.1)简单分页的4个参数
# page_size=api_settings.PAGE_SIZE # 每页大小,支持在settings.py里面配置 # page_query_param='page' # 查询每页的参数 # page_size_query_param=None # 指定每页的大小 # page_size_query_param=None # 每页最大显示多少
2)偏移分页(没什么用)from rest_framework.pagination import LimitOffsetPagination
from app01 import myserial # 序列化 from app01.auth import myPermission from app01.auth import MyThro from rest_framework.pagination import LimitOffsetPagination # 偏移分页,从第一页开始 class Book(APIView): authentication_classes = [myAuthen,] # 认证 permission_classes = [myPermission,] # 权限 throttle_classes = [MyThro,] # 频率 print('ok') def get(self,request): response = MyResponse() books=models.Book.objects.all() page = LimitOffsetPagination() page.default_limit = 2 # 默认显示2条 page_book = page.paginate_queryset(books,request,view=self) # http://127.0.0.1:8000/books/?&token=1d64b50ea99db6b66ab379dcfbfc5814 # 默认显示2条 # http://127.0.0.1:8000/books/?limit=3&token=1d64b50ea99db6b66ab379dcfbfc5814 # 根据limit设置的条数 ret = myserial.BookSer(instance=page_book,many=True) response.msg = '查询成功' response.data=ret.data return JsonResponse(response.get_dic,safe=False)
2.1)偏移分页使用小结
-from rest_framework.pagination import LimitOffsetPagination -生成一个对象 -调用对象的.page.paginate_queryset(books, request, view=self) -会有返回结果:把结果序列化,返回 -四个参数: 默认大小 default_limit = api_settings.PAGE_SIZE 查询的条数 limit_query_param = 'limit' 偏移的条数 offset_query_param = 'offset' 最多多少条 max_limit = None
3)加密分页。from rest_framework.pagination import CursorPagination
from app01 import myserial # 序列化 from app01.auth import myPermission from app01.auth import MyThro from rest_framework.pagination import CursorPagination # 加密分页 class Book(APIView): authentication_classes = [myAuthen,] # 认证 permission_classes = [myPermission,] # 权限 throttle_classes = [MyThro,] # 频率 def get(self,request): response = MyResponse() books=models.Book.objects.all() page = CursorPagination() page.ordering = 'nid' # book表的nid,按照nid排序 page.page_size = 2 page_book = page.paginate_queryset(books,request,view=self) # http://127.0.0.1:8000/books/?token=1d64b50ea99db6b66ab379dcfbfc5814 默认第一页 # http://127.0.0.1:8000/books/?cursor=cj0xJnA9NA%3D%3D&token=1d64b50ea99db6b66ab379dcfbfc5814 # ?cursor=随机字符串 ret = myserial.BookSer(instance=page_book,many=True) response.msg = '查询成功' response.data=ret.data return page.get_paginated_response(ret.data) # 包含返回上一页和下一页的随机字符串 cursor=随机字符串
3.1)加密分页小结
-from rest_framework.pagination import CursorPagination -生成一个对象 -调用对象的.page.paginate_queryset(books, request, view=self) -会有返回结果:把结果序列化,返回 -两个参数: 按什么排序 ordering = '-nid' page_size = 3
三、rest-framework之的路由控制:目的返回好看的json界面
1)使用实例归纳
1、继承from rest_framework.response import Response 2、视图函数中返回值:return Response(response.get_dic) 3、settings.py中添加app。 'rest_framework'
from rest_framework.renderers import HTMLFormRenderer,BrowsableAPIRenderer,JSONRenderer
renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
2)举例,视图函数
from app01 import myserial # 序列化 from app01.auth import myPermission from app01.auth import MyThro from rest_framework.pagination import CursorPagination # 加密分页 from rest_framework.renderers import BrowsableAPIRenderer,JSONRenderer from rest_framework.response import Response # 可以返回一个很好看的页面 class Book(APIView): authentication_classes = [myAuthen,] # 认证 permission_classes = [myPermission,] # 权限 renderer_classes = [BrowsableAPIRenderer,JSONRenderer] def get(self,request): response = MyResponse() books=models.Book.objects.all() page = CursorPagination() page.ordering = 'nid' # book表的nid,按照nid排序 page.page_size = 2 page_book = page.paginate_queryset(books,request,view=self) ret = myserial.BookSer(instance=page_book,many=True) response.msg = '查询成功' response.data=ret.data return Response(response.get_dic) # 返回页面,使用Response
注意:一定要使用页面访问测试该请求
3)全局设置
在settng中进行全局设置
REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer'] }
4)返回的页面是可以进行修改的
4)路由控制。视图类继承的ViewSetMixin (as_view中必须传参数,字典形式)
4.1)路由编写
url(r'^books/', views.Book.as_view({'get':'get_all'})),
4.2)视图函数编写
注意:from rest_framework.viewsets import ViewSetMixin
class Book(ViewSetMixin,APIView): 继承的ViewSetMixin 需要写在前面,才会这里面的as_view的方法
from rest_framework.response import Response # 可以返回一个很好看的页面 from rest_framework.viewsets import ViewSetMixin class Book(ViewSetMixin,APIView): def get_all(self,request): response = MyResponse() books=models.Book.objects.all() ret = myserial.BookSer(instance=books,many=True) response.msg = '查询成功' response.data=ret.data return Response(response.get_dic) # 返回页面,使用Response
5)路由传参格式
5.1)路由编写
url(r'^books.(?P<format>\w+)/', views.Book.as_view()),
5.2)视图函数
from rest_framework.response import Response class Book(APIView): def get(self,request,*args,**kwargs): response = MyResponse() books=models.Book.objects.all() ret = myserial.BookSer(instance=books,many=True) response.msg = '查询成功' response.data=ret.data return Response(response.get_dic)
5.3)网页请求测试
http://127.0.0.1:8000/books.json/?token=1d64b50ea99db6b66ab379dcfbfc5814
5.6)路由总结
url控制 1) 原始的的url -url(r'^books/', views.Book.as_view()), 2) 视图类继承的ViewSetMixin (as_view中必须传参数,字典形式) -url(r'^books/', views.Book.as_view('get':'get_all')), 3) 全自动路由(自动生成路由)几乎不用 from rest_framework import routers router = routers.DefaultRouter() # 2个参数,一个是匹配的路由,一个是视图中写的CBV的类 router.register('book',views.Book) urlpatterns = [ url(r'', include(router.urls)), ]
原文链接:https://www.cnblogs.com/liuqingzheng/articles/9766413.html
四、版本控制
1)用get类进行控制:from rest_framework.versioning import QueryParameterVersioning
settting中进行配置
REST_FRAMEWORK = { ........ 'DEFAULT_VERSION': 'v1', # 默认版本(从request对象里取不到,显示的默认值) 'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本 'VERSION_PARAM': 'version' # URL中获取值的key }
视图函数:
from rest_framework.versioning import QueryParameterVersioning from rest_framework.response import Response class Book(APIView): versioning_class = QueryParameterVersioning def get(self,request,*args,**kwargs): response = MyResponse() print(request.version) books=models.Book.objects.all() ret = myserial.BookSer(instance=books,many=True) response.msg = '查询成功' response.data=ret.data return Response(response.get_dic)
请求测试: http://127.0.0.1:8000/books/?version=v2&token=1d64b50ea99db6b66ab379dcfbfc5814
2) 使用路由控制
视图函数编写
from rest_framework.versioning import URLPathVersioning from rest_framework.response import Response class Book(APIView): versioning_class = URLPathVersioning def get(self,request,*args,**kwargs): response = MyResponse() print(request.version) books=models.Book.objects.all() ret = myserial.BookSer(instance=books,many=True) response.msg = '查询成功' response.data=ret.data return Response(response.get_dic)
路由控制
url的2种写法都可以 url(r'^(?P<version>[v1|v2]+)/books/', views.Book.as_view()), # url(r'^[v1|v2]+/books/', views.Book.as_view()),
setting里面的配置可以注释掉,基于这种路由配置,setting里面就可以不用配置了
请求测试: http://127.0.0.1:8000/v2/books/?token=1d64b50ea99db6b66ab379dcfbfc5814
2.1) 路由编写的另一种格式
url(r'^(?P<version>\w+)/books/', views.Book.as_view()),
需要在setting配置能访问的版本号
'DEFAULT_VERSION': 'v1', # 默认版本(从request对象里取不到,显示的默认值) 'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本 'VERSION_PARAM': 'version', # URL中获取值的key
3)视图总结
# 第一种,默认的版本控制。(无用) #http://127.0.0.1:8000/books/?version=v1&token=1d64b50ea99db6b66ab379dcfbfc581 # print(request.GET.get('version')) # print(request.query_params.get('version')) # 第二种,QueryParameterVersioning控制 settings.py配置 REST_FRAMEWORK = { 'DEFAULT_VERSION': 'v1', # 默认版本(从request对象里取不到,显示的默认值) 'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本 'VERSION_PARAM': 'version' # URL中获取值的key } 视图函数导入 from rest_framework.versioning import QueryParameterVersioning versioning_class = QueryParameterVersioning 路由配置 url(r'^books/', views.Book.as_view()), 请求测试:http://127.0.0.1:8000/books/?version=v2&token=1d64b50ea99db6b66ab379dcfbfc5814 # 第三种 settings.py配置可以不用配置 视图函数导入 from rest_framework.versioning import URLPathVersioning versioning_class = URLPathVersioning url的2种写法都可以 url(r'^(?P<version>[v1|v2]+)/books/', views.Book.as_view()), # url(r'^[v1|v2]+/books/', views.Book.as_view()), 请求测试:http://127.0.0.1:8000/v2/books/?token=1d64b50ea99db6b66ab379dcfbfc5814 3.1)url(r'^(?P<version>\w+)/books/', views.Book.as_view()), 添加settings的配置 'DEFAULT_VERSION': 'v1', # 默认版本(从request对象里取不到,显示的默认值) 'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本 'VERSION_PARAM': 'version' # URL中获取值的key
原文链接: https://www.cnblogs.com/liuqingzheng/articles/9766422.html