Rest_framework之版本控制、响应器和分页器

一、访问频率补充

频率:
自定义:
1 定义一个类MyThrottles
allow_request(频率限制的逻辑) ==》这两个函数都是派生出来的,继承的类里面封装的。
wait(返回一个数字,给用户提示,还差多少秒)
2 局部使用:throttle_classes=[MyThrottles,]
3 全局使用:'DEFAULT_THROTTLE_CLASSES':['utils.common.MyThrottles',],
用内置的:(可以控制ip,和userid)
1 写一个类,继承SimpleRateThrottle
属性:scope = 'xxx'  ===》scope是源码里的参数,必须要写
重写方法:get_cache_key

 1 from rest_framework.throttling import SimpleRateThrottle
 2 
 3 
 4 class VisitThrottle(SimpleRateThrottle):
 5     # {IP:[]}
 6     # {id:[]}
 7     scope = 'xxx'  # 这个必须要写 因为源码里有
 8 
 9     def get_cache_key(self, request, view):  # 重写get_cache_key方法
10         # ip=request.META.get('REMOTE_ADDR')  根据IP来限制访问频率 remote_addr如果是用的代理,获取的是代理IP,否则是主机的IP
11         # 用户一分钟只能访问5次
12         pk = request.user.pk  # 根据用户的主键限制访问频率,默认是通过IP限制,可看源码
13         return pk

 

去setting里配置:'DEFAULT_THROTTLE_RATES':{
# 'xxx':'5/m',  ===》这里的xxx是scope设定的值。
'xxx':'5/m',
}
2 局部使用:throttle_classes=[MyThrottles,]
3 全局使用:'DEFAULT_THROTTLE_CLASSES':['utils.common.MyThrottles',],
补充:
认证,想局部取消(禁用)===》只需要在认证的地方加上下面的:
  authentication_classes=[]

 

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

代码演示如下:

 1 class MyThrottles():
 2     VISIT_RECORD = {}
 3     def __init__(self):
 4         self.history=None
 5     def allow_request(self,request, view):
 6         #(1)取出访问者ip
 7         # print(request.META)
 8         ip=request.META.get('REMOTE_ADDR')
 9         import time
10         ctime=time.time()
11         # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问
12         if ip not in self.VISIT_RECORD:
13             self.VISIT_RECORD[ip]=[ctime,]
14             return True
15         self.history=self.VISIT_RECORD.get(ip)
16         # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
17         while self.history and ctime-self.history[-1]>60:
18             self.history.pop()
19         # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
20         # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
21         if len(self.history)<3:
22             self.history.insert(0,ctime)
23             return True
24         else:
25             return False
26     def wait(self):
27         import time
28         ctime=time.time()
29         return 60-(ctime-self.history[-1])

 


二、版本控制:
1 127.0.0.1/course/?version=v100000   ===》常用的两种版本书写方式,url带参数形式的

versioning_class = QueryParameterVersioning   只能写成这种形式的,因为源码里不是和处理以前列表形式一样来处理这个


用from rest_framework.versioning import QueryParameterVersioning
在视图类里:
versioning_class=QueryParameterVersioning(**不再是列表)
在setting里配置:
REST_FRAMEWORK={
'VERSION_PARAM':'version',
'DEFAULT_VERSION':'v2',
'ALLOWED_VERSIONS':['v1','v2']
}
视图类里:
request.version  ===》 版本号

127.0.0.1/v1/course/   ===》这种形式比较常用 

versioning_class = URLPathVersioning   


用from rest_framework.versioning import URLPathVersioning
在视图类里:
versioning_class=URLPathVersioning**不再是列表)
在setting里配置:
REST_FRAMEWORK={
'VERSION_PARAM':'version',
'DEFAULT_VERSION':'v2',
'ALLOWED_VERSIONS':['v1','v2']
}
视图类里:
request.version

3 反向解析(了解)

urls

 1 from django.conf.urls import url
 2 from django.contrib import admin
 3 from app01 import views
 4 urlpatterns = [
 5     url(r'^admin/', admin.site.urls),
 6     url(r'^testversion/', views.Test.as_view()),
 7     url(r'^(?P<version>[v1|v2|v3]+)/testversion/', views.Test2.as_view(),name='ttt'),
 8     url(r'^testres', views.Test3.as_view()),
 9     url(r'^page', views.Page.as_view()),
10 ]

settings里相关配置

1 REST_FRAMEWORK={
2     'VERSION_PARAM':'version',
3     'DEFAULT_VERSION':'v2',
4     'ALLOWED_VERSIONS':['v1','v2']
5 }

 

views

 1 from django.shortcuts import render, HttpResponse
 2 
 3 # Create your views here.
 4 from app01 import models
 5 from rest_framework.views import APIView
 6 from rest_framework.response import Response
 7 
 8 from rest_framework.versioning import QueryParameterVersioning, URLPathVersioning
 9 
10 版本控制
11 class Test(APIView):
12     versioning_class = QueryParameterVersioning
13 
14     def get(self, request, *args, **kwargs):
15         print(request.version)
16 
17         return Response('ok')
18 
19 
20 from django.urls import reverse
21 
22 反向解析  仅作了解 用的比较少
23 class Test2(APIView):
24     versioning_class = URLPathVersioning
25 
26     def get(self, request, *args, **kwargs):
27         print(request.version)
28         url = request.versioning_scheme.reverse(viewname='ttt', request=request)
29         print(url)
30         url2 = reverse(viewname='ttt', kwargs={'version': 'v1'})
31         print(url2)
32 
33         return Response('ok ttest2')

 

 


三、响应器:
以后项目中用:(返回的格式,只是json格式)
REST_FRAMEWORK={
'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer',],
}
补充一点:
查找模板的时候:先从自己app里找,找不到去项目,再找不到,去各个app里找

 views

 1 from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer, AdminRenderer
 2 
 3 
 4 class Test3(APIView):
 5     renderer_classes=[BrowsableAPIRenderer]
 6     def get(self, request, *args, **kwargs):
 7         return Response({
 8             'name': 'qlz',
 9             'age': 18,
10             'name1': 'qlz',
11             'age2': 18,
12         })

 

settings

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer'],
 
}

 

 

四、分页

1 简单分页
127.0.0.1/course/page=3
PageNumberPagination
#每页显示多少条api_settings.PAGE_SIZE
#page_size =
#查询指定页码的重命名
#page_query_param = 'page'
#指定每页显示条数
#page_size_query_param = None
#限制每页显示最大条数
#max_page_size = None

2 偏移分页
127.0.0.1/course/offset=10&limit=5
LimitOffsetPagination
# default_limit:默认显示多少条
# max_limit:最大显示多少条
# limit_query_param:重新命名limit(limit=4:表明显示四条,受max_limit的限制)
# offset_query_param:指定查询的标杆名(offset=1:表明从第二条开始,往后偏移)
3 加密分页
后台返回的url:127.0.0.1/course/page=dfgeg
CursorPagination
cursor_query_param = 'cursor':查询的名字
page_size = api_settings.PAGE_SIZE:每页显示的条数
ordering = '-created' :按谁排序

补充:(1)修改数据属性的方式:
1 再setting里配置每页条数
2 写一个类,继承它,属性重写
3 再对象里修改
(2)my_page.get_paginated_response(ser.data)
# 对Response做了封装,返回内容里有总条数,上一页,下一页的链接

views

 1 from rest_framework.serializers import ModelSerializer
 2 from rest_framework import serializers
 3 
 4 
 5 class BookSer(serializers.ModelSerializer):
 6     class Meta:
 7         model = models.Book
 8         fields = '__all__'
 9 
10 
11 from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
12 
13 
14 # class Page(APIView):
15 #     def get(self,request,*args,**kwargs):
16 #         ret=models.Book.objects.all()
17 #         my_page=PageNumberPagination()
18 #         my_page.page_size=2
19 #         my_page.page_size_query_param='size'
20 #         my_page.max_page_size=5
21 #
22 #         page_list=my_page.paginate_queryset(ret,request,self)
23 #         ser=BookSer(instance=page_list,many=True)
24 #         # 1 再setting里配置每页条数
25 #         # 2 写一个类,继承它,属性重写
26 #         # 3 再对象里修改
27 #         '''
28 #         每页显示多少条api_settings.PAGE_SIZE
29 #         page_size =
30 #         查询指定页码的参数
31 #         page_query_param = 'page'
32 #         指定每页显示条数
33 #         page_size_query_param = None
34 #         限制每页显示最大条数
35 #         max_page_size = None
36 #         '''
37 #
38 #         return Response(ser.data)
39 
40 # class Page(APIView):
41 #     def get(self,request,*args,**kwargs):
42 #         ret=models.Book.objects.all()
43 #         my_page=LimitOffsetPagination()
44 #         my_page.default_limit=3
45 #         my_page.max_limit=5
46 #
47 #
48 #         page_list=my_page.paginate_queryset(ret,request,self)
49 #         ser=BookSer(instance=page_list,many=True)
50 #         # 1 再setting里配置每页条数
51 #         # 2 写一个类,继承它,属性重写
52 #         # 3 再对象里修改
53 #         '''
54 #         default_limit:默认显示多少条
55 #         max_limit:最大显示多少条
56 #         limit_query_param:重新命名limit(limit=4:表明显示四条,受max_limit的限制)
57 #         offset_query_param:指定查询的标杆名(offset=1:表明从第二条开始,往后偏移)
58 #         '''
59 #
60 #         # return Response(ser.data)
61 #         # 对Response做了封装,返回内容里有总条数,上一页,下一页的链接
62 #         return my_page.get_paginated_response(ser.data)
63 
64 
65 class Page(APIView):
66     def get(self, request, *args, **kwargs):
67         ret = models.Book.objects.all()
68         my_page = CursorPagination()
69         my_page.ordering = 'id'
70         my_page.page_size = 2
71         page_list = my_page.paginate_queryset(ret, request, self)
72         ser = BookSer(instance=page_list, many=True)
73         # 1 再setting里配置每页条数
74         # 2 写一个类,继承它,属性重写
75         # 3 再对象里修改
76         '''
77             cursor_query_param = 'cursor':查询的名字
78             page_size = api_settings.PAGE_SIZE:每页显示的条数
79             ordering = '-created'  :按谁排序
80         '''
81 
82         # return Response(ser.data)
83         # 对Response做了封装,返回内容里有总条数,上一页,下一页的链接
84         return my_page.get_paginated_response(ser.data)
85         # return Response(ser.data)
Views

 

自己封装response对象
。。。。



作业:
1 前端操作cookie
2 频率显示中文(去源码里找,替换)
3 版本控制,不在setting里配置,实现
5 redis安装上(windows/linux)
4 axios
5 cc视频 ==》路飞学城用的视频代理,现在一般不自己搞代理,浪费人力物力,买的代理划算。

posted @ 2018-10-23 19:33  Roc_Atlantis  阅读(178)  评论(0编辑  收藏  举报