过滤与排序、分页、异常处理

过滤和排序

内置

# 查询所有才需要过滤(根据条件过滤),排序(按某个规则排序)

# 内置过滤类使用,在视图类中配置
from rest_framework.filters import SearchFilter
class BookView(ViewSetMixin,ListAPIView):
    # 在视图类中配置,最顶层的类至少是GenericAPIView
    filter_backends = [SearchFilter,]
    # 过滤条件,按名字过滤
    search_fields=['name','publish']
    
# 查询
http://127.0.0.1:8000/books/?search=达   # 出版社中或名字中有'达'就能查询出来
 

## 内置排序类(既有排序,又有过滤)
from rest_framework.filters import OrderingFilter,SearchFilter
class BookView(ViewSetMixin,ListAPIView):

    # 在视图类中配置,最顶层的类至少是GenericAPIView
    filter_backends = [SearchFilter,OrderingFilter,]
    # 过滤条件,按名字过滤
    search_fields=['name']
    # 按哪个字段排序
    ordering_fields=['price','id']


# 排序
http://127.0.0.1:8000/books/?ordering=price,-id

第三方

        
# 第三方pip3 install django-filter
# 视图类中
from django_filters.rest_framework import DjangoFilterBackend
class BookView(ViewSetMixin,ListAPIView):

    # 在视图类中配置,最顶层的类至少是GenericAPIView
    filter_backends = [DjangoFilterBackend,]
    # 按名字过滤
    filter_fields=['name','price']
    
# 查询时
http://127.0.0.1:8000/books/?name=红楼梦
http://127.0.0.1:8000/books/?name=四方达&price=15

# filter_backends的列表中可以写多个方法,使用时会按顺序进行,将前一个的结果交给后一个处理

自定义


分页

  • 只有查询所有的接口才使用分页功能,网页中的下一页,app的下滑加载更多
  • 使用:
    • 先新建一个pagination.py文件,写一个类,继承对应的分页类,重写几个类属性
    • 在视图类中卑职分页类即可,类属性pagination_class=自己写的类
    • 配置分页类需要继承GenericAPIView及子类,才能使用。

基本分页

from rest_framework.pagination import PageNumberPagination
class CommonPageNumberPagination(PageNumberPagination):
    page_size = 2  # 每页的条数
    page_query_param = 'page'  # 查询时用的参数
    # http://127.0.0.1:8000/books/?page=2
    page_size_query_param = 'size'  # 通过这个参数更改返回的条数
    # 第一页返回四条 http://127.0.0.1:8000/books/?page=1&size=4
    max_page_size = None  # 更改一页最多显示的条数
    
class BookView(ViewSetMixin, ListAPIView):
    pagination_class = CommonPageNumberPagination

偏移分页

from rest_framework.pagination import LimitOffsetPagination
class CommonLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 2  # 显示多少条
    limit_query_param = 'limit'  # limit的参数
	offset_query_param = 'offset'  # offset偏移的查询参数
    max_limit = 5  # 最大显示条数,为5
    
class BookView(ViewSetMixin, ListAPIView):
    pagination_class = LimitOffsetPagination
    
# 在offset位置,向后查看limit条数据
# http://127.0.0.1:8000/book/?limit=3&offset=5 ,查看6开始的3条数据

游标分页

from rest_framework.pagination import CursorPagination
class CommonCursorPagination(CursorPagination):
    page_size = 3  # 每页显示多少条
    cursor_query_param = 'cursor'  # 查询条件
    ordering = 'id'  # 排序,按id排序
    page_size_query_param = 'size'  # 通过这个参数决定每页显示多少条
    max_page_size = 5  # 每页最大显示多少条
    
class BookView(ViewSetMixin, ListAPIView):
    pagination_class = CommonCursorPagination
    
http://127.0.0.1/four/students/?cursor=cD0xNQ%3D%3D
# 类似于将页码加密,只能通过上一页下一页来进行翻页
# 优点:速度最快,数据量越大越有优势
# 缺点:只能上一页下一页,不能跳到指定某一页

继承APIView实现分页

class BookViewALL(APIView):

    def get(self,request,*args,**kwargs):
        book_list=Books.objects.all()
        #实例化得到一个对象
        pagination=CommonPageNumberPagination()
        # 修改对象属性,我们继承了自己定义的类,这里不需要改
        # pagination.page_query_param='page'

        #调用对象方法,传入要分页的数据,book_list,返回分页号的数据
        book_list2=pagination.paginate_queryset(book_list,request,self)
        ser=BookSerializer(instance=book_list2,many=True)
        
        res={'pre':pagination.get_previous_link(),'next':pagination.get_next_link(),'count':pagination.page.paginator.count,'data':ser.data}
        return Response(res)

        # 另一种返回方式
        return pagination.get_paginated_response(ser.data)

异常处理

1 全局统一捕获异常,返回固定的格式  {code:999,msg:'未知错误'}

2 使用步骤
	-新建一个utils.py
	-写一个函数(模仿默认的)
    -在配置文件中配置
# 默认配置文件中:'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'


#  写函数
from rest_framework.views import exception_handler
from rest_framework.response import Response
def common_exception_handler(exc, context):
    # 记录日志,context中有view对象和request对象
    print(context['request'].META.get('REMOTE_ADDR'))
    response=exception_handler(exc, context)
    if response:  # 处理了drf的异常
        data = {'code': 999, 'msg': '错误','detail':response.data}
    else: # 不知道的异常
        data = {'code':999,'msg':'未知错误'}
    return Response(data)

# 配置文件配置
REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'app01.utils.common_exception_handler',
}

posted @ 2021-07-23 21:23  zheng-sn  阅读(96)  评论(0)    收藏  举报