DRF之排序

内置排序

  1. from rest_framework.generics import ListAPIView
  2. from frequence.serializer import BookSerializer
  3. from rest_framework.filters import OrderingFilter
  4. from frequence.models import Book
  5. class BookView(ListAPIView):
  6. queryset = Book.objects.all()
  7. serializer_class = BookSerializer
  8. filter_backends = [OrderingFilter] # 排序组件导入
  9. ordering_fields = ("id", "price") # 可以使用id排序,也可以使用价格排序

DRF之过滤

内置过滤器

使用

  1. from rest_framework.filters import SearchFilter
  2. #继承了GenericAPIView的视图类,只要加入,两个类属性
  3. class BookView(GenericViewSet, ListModelMixin):
  4. serializer_class = BookSerializer
  5. queryset = Book.objects.all()
  6. filter_backends = [SearchFilter,]
  7. search_fields=['name','price'] # 按name或price过滤,模糊查询
  1. http://127.0.0.1:8000/api/v1/books?search=测试

第三方过滤器

  1. pip3 install django-filter

settings.py里面注册app

  1. INSTALLED_APPS = [
  2. ...
  3. 'rest_framework',
  4. 'django_filters',
  5. ]

使用

  1. from django_filters.rest_framework import DjangoFilterBackend
  2. class BookView(GenericViewSet, ListModelMixin):
  3. serializer_class = BookSerializer
  4. queryset = Book.objects.all()
  5. filter_backends = [DjangoFilterBackend, ]
  6. filter_fields = ['name', 'price']
  1. http://127.0.0.1:8000/api/v1/books?name=测试&price=123

全局使用

  1. REST_FRAMEWORK = {
  2. 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
  3. }

局部使用

  1. from django_filters.rest_framework import DjangoFilterBackend # 导入过滤组件
  2. class BookAPI(ListAPIView):
  3. queryset = Book.objects.all()
  4. serializer_class = BookModelSerializers
  5. filter_backends = [DjangoFilterBackend, ] # 过滤组件导入
  6. filter_fields = ("id","price") # 可以使用id过滤,也可以使用价格过滤

局部禁用

  1. class BookAPI(ListAPIView):
  2. filter_backends = [] # 设置为空
  3. queryset = Book.objects.all()
  4. serializer_class = BookModelSerializers

自定义过滤器

步骤

  • 写一个类,继承BaseFilterBackend
  • 重写filter_queryset方法

使用

views.py

  1. from .throttling import FilterName
  2. class BookView(GenericViewSet, ListModelMixin):
  3. serializer_class = BookSerializer
  4. queryset = Book.objects.all()
  5. filter_backends = [FilterName, ]

throttling

  1. class FilterName(BaseFilterBackend):
  2. def filter_queryset(self, request, queryset, view):
  3. name = request.query_params.get('name')
  4. price = request.query_params.get('price_gt')
  5. if name and price:
  6. return queryset.filter(name__contains=name, price__gt=price)
  7. return queryset.filter()

DRF之分页

分页器 中文 介绍
PageNumberPagination 普通分页 非常常用 拥有上一页下一页 同时也可以做诸如1,2,3,4这样的跳转页数
LimitOffsetPagination 偏移分页 相对使用较少 有一个基准点 可以根据这个基准点进行左偏移和右偏移
CursorPagination 游标分页 效率最高,速度最快只有上一页和下一页
不可以做页数的跳转
  • APIView:分页需要自己写
  • GenericAPIView+ListModelMixin:直接用

基本分页

参数

参数 释义
page_size = 3 每页显示的条数
page_query_param = ‘page’ 查询的时候指定跳转到第几页
page_size_query_param = ‘size’ 查询的时候指定每页显示的条数
max_page_size = 5 每页最大显示条数(相当于手动限制)

使用

page.py

  1. from rest_framework.pagination import PageNumberPagination
  2. # 基本分页:正常的查第几页,每页显示多少条的方式
  3. class CommonPageNumberPagination(PageNumberPagination):
  4. #4个类属性
  5. page_size = 2 #每页显示条数
  6. page_query_param = 'page' # 查询页码参数 ?page=10
  7. page_size_query_param = 'size' # ?page=3&size=5000
  8. max_page_size = 5 # 可以通过size控制每页显示的条数,但是通过这个参数控制最多显示多少条

偏移分页

参数

参数 释义
default_limit = 2 每页默认显示条数
limit_query_param = ‘limit’ 查询时,指定显示几条
offset_query_param = ‘offset’ (标杆)查询时,指定的起始位置是哪里
max_limit = 5 查询时,最多返回几条

使用

page.py

  1. from rest_framework.pagination import LimitOffsetPagination
  2. # 偏移分页
  3. class CommonLimitOffsetPagination(LimitOffsetPagination):
  4. default_limit = 2 # 每页显示多少条
  5. limit_query_param = 'limit' # 取多少条
  6. offset_query_param = 'offset' #从第0个位置偏移多少开始取数据
  7. max_limit = 5 # 最大限制条数
  8. # offset=6&limit=90000
  9. # http://127.0.0.1:8000/books/?limit=3&offset=3 # 从第三条开始取3条
  10. # limit_query_description = _('Number of results to return per page.')

游标分页

参数

参数 释义
page_size = 2 每页显示的条数
ordering = ‘pk’ 排序字段(必填)
cursor_query_param = ‘cursor’ 每一页查询的key
page_size_query_param = ‘size’ 查询时,每一页显示几条
max_page_size 查询时,最多返回几条

使用

page.py

  1. # 游标分页针对于大数据量分页效率高---》可控性差--->只能选择上一页和下一页,不能直接跳转到某一个
  2. class CommonCursorPagination(CursorPagination):
  3. cursor_query_param = 'cursor' # 查询的名字 等同于 page=xx
  4. page_size = 3 # 每页显示多少条
  5. ordering = 'pk' # 排序规则,必须是表中有的字段,一般用id
  6. # http://127.0.0.1:8000/books/?cursor=cD0z

view.py

  1. pagination_class = MyPageNumberPagination

继承APIView实现分页

  1. # APIView实现分页
  2. from rest_framework.views import APIView
  3. from rest_framework.viewsets import ViewSet
  4. from rest_framework.response import Response
  5. class BookView(ViewSet):
  6. def list(self,request):
  7. books=Book.objects.all()
  8. # 分页
  9. # paginator=PageNumberPagination()
  10. paginator=CommonLimitOffsetPagination()
  11. #分页过后的数据
  12. qs=paginator.paginate_queryset(books,request,self)
  13. #序列化
  14. ser=BookSerializer(qs,many=True)
  15. # 第一种方式:每页总条数,上一页,下一页
  16. # return Response(ser.data)
  17. # 第二种:自己凑
  18. # return Response({
  19. # 'count':books.count(),
  20. # 'next': paginator.get_next_link(),
  21. # 'previous':paginator.get_previous_link(),
  22. # 'results': ser.data
  23. # })
  24. # 第三种;直接使用分页类的方法
  25. return paginator.get_paginated_response(ser.data)

DRF之异常处理

自定义全局异常

utils.py

  1. # 第一步:写一个函数
  2. from rest_framework.views import exception_handler
  3. from rest_framework.response import Response
  4. def common_exception_handler(exc, context):
  5. # 正常来讲,在这里需要记录日志
  6. print(context['view']) # 视图类的对象
  7. print(context['request']) #当前请求的对象----》ip,用户id,当前时间,请求地址来
  8. view=context['view']
  9. request=context['request']
  10. print('ip地址为:%s的用户,访问:%s 视图类,报错了,请求地址是:%s'%(request.META.get('REMOTE_ADDR'),str(view),request.path))
  11. response=exception_handler(exc, context)
  12. if response: # 这是drf的异常,其实人家已经处理了,但是不符合我的格式 {code:999,msg:错误}
  13. res=Response({'code':999,'msg':response.data.get('detail')})
  14. else:
  15. # res=Response({'code':998,'msg':'服务器错误,请联系系统管理员'})
  16. res=Response({'code':998,'msg':str(exc)})

settings.py

  1. REST_FRAMEWORK = {
  2. 'EXCEPTION_HANDLER':'frequence.utils.capture_exception'
  3. }