DRF频率类
# 某个接口,限制访问频率----》可以根据IP,用户id # 频率类的编写 -第一步:写一个类,继承SimpleRateThrottle -第二步:重写get_cache_key方法 -第三步:返回什么,就以什么做限制 -第四步:写一个类属性 -scope = '3_min' -第五步:配置文件中配置 REST_FRAMEWORK = { # 频率类中scope对应的值 '3_min':'3/m' # 数字/s m h d } -第六步:局部和全局使用 局部用:视图类中 class BookView(APIView): throttle_classes = [IPThrottle, ] 全局用:配置文件 REST_FRAMEWORK = { "DEFAULT_THROTTLE_RATES": { # 频率类中scope对应的值 '3_min': '3/m' # 数字/s m h d }, 'DEFAULT_THROTTLE_CLASSES':['app01.throttling.IPThrottle',] }
频率类
class IPThrottle(SimpleRateThrottle): # 写一个类属性,字符串 scope = '3_min' def get_cache_key(self, request, view): # return 什么就一什么做限制, 返回ip 返回用户id return request.META.get('REMOTE_ADDR') # return request.user.id # 返回用户id
视图类
class BookView(APIView): throttle_classes = [IPThrottle, ] def get(self, request): return Response('ok') def throttled(self, request, wait): from rest_framework.exceptions import Throttled class MyThrottled(Throttled): default_detail = '超限制乐' extra_detail_singular = '还有 {wait} 描述.' extra_detail_plural = '出了 {wait} 秒.' raise MyThrottled(wait)
配置文件
REST_FRAMEWORK = { "DEFAULT_THROTTLE_RATES": { # 频率类中scope对应的值 '3_min': '3/m', # 数字/s m h d 'anon':'4/h', 'user':'5/m' }, 'DEFAULT_THROTTLE_CLASSES':['app01.throttling.IPThrottle',] }
DRF内置认证类、权限类、频率类
# 内置的认证---》跟咱们项目都补贴和,咱们不用,咱们自己根据自己的规则写 -SessionAuthentication:之前老的session认证登录方式用,后期都不用了 -BasicAuthentication :基本认证方式,咱们不用 -TokenAuthentication :使用token认证方式,有用,但是咱们也是自己写的 # 内置的权限类 -IsAdminUser :校验是不是auth的超级管理员权限 -IsAuthenticated:后面会用到,验证用户是否登录了,登录了才有权限,没登录就没有权限 -IsAuthenticatedOrReadOnly:知道有这个东西即可 # 内置的频率类 -UserRateThrottle :限制登录用户的频率,需要配置配置文件 -AnonRateThrottle:登录用户不限制,未登录用户限制,需要配置配置文件
DRF排序
# 排序功能接口只针对于:获取所有接口 # 继承了GenericAPIView的视图类,只要加入,两个类属性 class BookView(GenericViewSet, ListModelMixin): serializer_class = BookSerializer queryset = Book.objects.all() filter_backends = [OrderingFilter, ] ordering_fields = ['price','id' ] # 访问的时候 http://127.0.0.1:8000/api/v1/books?ordering=price # 按price升序 http://127.0.0.1:8000/api/v1/books?ordering=-price # 按price降序 http://127.0.0.1:8000/api/v1/books?ordering=price,id # 先按价格升序排,价格一样,再按id升序排
DRF过滤
# 查询名字为XXX的所有图书:获取所有接口 # 内置的过滤使用---》不能指定查询那个字段,模糊查询 -继承了GenericAPIView的视图类,只要加入,两个类属性 class BookView(GenericViewSet, ListModelMixin): serializer_class = BookSerializer queryset = Book.objects.all() filter_backends = [SearchFilter,] search_fields=['name','price'] # 按name或price过滤 -使用 http://127.0.0.1:8000/api/v1/books?search=XXX # search= xx ----》具体查询是 name like xx or price like xx # 我们想http://127.0.0.1:8000/api/v1/books?name=XXX&price=12---》第三方django-filter -安装:pip3 install django-filter -继承了GenericAPIView的视图类,只要加入,两个类属性 from django_filters.rest_framework import DjangoFilterBackend class BookView(GenericViewSet, ListModelMixin): serializer_class = BookSerializer queryset = Book.objects.all() filter_backends = [DjangoFilterBackend, ] filter_fields = ['name', 'price'] -使用 http://127.0.0.1:8000/api/v1/books?name=XXX&price=11 # 自定义过滤器---》完成更多查询操作 -写一个类,继承BaseFilterBackend -重写filter_queryset方法 -配置在视图类中 from .throttling import FilterName class BookView(GenericViewSet, ListModelMixin): serializer_class = BookSerializer queryset = Book.objects.all() filter_backends = [FilterName, ] # 既有过滤又有排序 class BookView(GenericViewSet, ListModelMixin): serializer_class = BookSerializer queryset = Book.objects.all() filter_backends = [FilterName, OrderingFilter] ordering_fields = ['price', ] # 源码分析,为什么这么配置就生效 -GenericAPIView的方法 def filter_queryset(self, queryset): for backend in list(self.filter_backends): queryset = backend().filter_queryset(self.request, queryset, self) return queryset
DRF自定义频率类
''' 自定义的逻辑: -(1)取出访问者ip {192.168.1.12:[访问时间3,访问时间2,访问时间1],192.168.1.12:[],192.168.1.14:[]} -(2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走 -(3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间, -(4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过 -(5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败 '''
from rest_framework.throttling import BaseThrottle class MyThrottling(): VISIT_RECORD = {} def __init__(self): self.history = None def allow_request(self, request, view): # (1)取出访问者ip 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])
DRF三种分页方式
PageNumberPagination---基本分页
前端访问网址形式:GET http://127.0.0.1:8000/students/?page=4
可以在子类中定义的属性:
- page_size 每页数目
- 前端访问网址形式:page_query_param 前端发送的页数关键字名,默认为”page”
- page_size_query_param 前端发送的每页数目关键字名,默认为None
- max_page_size 前端最多能设置的每页数量
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class BookPagination(PageNumberPagination): page_size = 2 # 默认每页展示的条数 page_query_param = 'page' # 查询页码的参数 page_size_query_param = 'size' # 控制每页显示的条数 ?size=3 max_page_size = 5 # 控制每页最多显示多少条数
LimitOffsetPagination---偏移分页
前端访问网址形式:GET http://127.0.0.1/four/students/?limit=100&offset=400
可以在子类中定义的属性:
- default_limit 默认限制,默认值与
PAGE_SIZE
设置一直 - limit_query_param limit参数名,默认’limit’
- offset_query_param offset参数名,默认’offset’
- max_limit 最大limit限制,默认None
class CommonLimitOffsetPagination(LimitOffsetPagination): default_limit = 2 # 每页显示多少条 limit_query_param = 'limit' # 取多少条 offset_query_param = 'offset' #从第0个位置偏移多少开始取数据 max_limit = 5 # 最大限制条数
CursorPagination---游标分页
前端访问网址形式:GET http://127.0.0.1/four/students/?cursor=cD0xNQ%3D%3D
可以在子类中定义的属性:
- cursor_query_param:默认查询字段,不需要修改
- page_size:每页数目
- ordering:按什么排序,需要指定
class CommonCursorPagination(CursorPagination): cursor_query_param = 'cursor' # 查询的名字 等同于 page=xx page_size = 3 # 每页显示多少条 ordering = 'id' # 排序规则,必须是表中有的字段,一般用id
继承APIView实现分页
from rest_framework.views import APIView from rest_framework.viewsets import ViewSet from rest_framework.response import Response class BookView(ViewSet): def list(self,request): books=Book.objects.all() # 分页 # paginator=PageNumberPagination() paginator=CommonLimitOffsetPagination() # 实例化自己写的分页类 #分页过后的数据 qs=paginator.paginate_queryset(books,request,self) #序列化 ser=BookSerializer(qs,many=True) # 第一种方式:每页总条数,上一页,下一页 # return Response(ser.data) # 第二种:自己凑 # return Response({ # 'count':books.count(), # 'next': paginator.get_next_link(), # 'previous':paginator.get_previous_link(), # 'results': ser.data # }) # 第三种;直接使用分页类的方法 return paginator.get_paginated_response(ser.data)
标签:return,price,queryset,page,class,self,DRF From: https://www.cnblogs.com/-sunflower-/p/16777561.html