DRF过滤排序分页异常处理的过程记录

 更新时间:2021年07月12日 09:29:56   作者:Mr-Yang  
在写django drf的时候会遇到搜索,以及过滤的情况,这篇文章主要给大家介绍了关于DRF过滤排序分页异常处理的相关资料,需要的朋友可以参考下

一、过滤

对于列表数据要通过字段来进行过滤,就需要添加 django-filter 模块

使用方法:

# 1、注册,在app中注册 settings.py
INSTALLED_APPS = [
    'django_filters',
]

# 2、settings.py 配置
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
    )
}

# 3、在视图中添加filter_fields属性,指定过滤的字段
class BooksView(ModelViewSet):
    queryset = Books.objects.all()
    serializer_class = BooksSerializer

    filter_fields = ('title',) # 配置可以按照哪个字段来过滤
    
# http://127.0.0.1:8000/books/?title=红楼梦

二、排序

排序可以使用 Rest Framework 提供的 OrderingFilter 来快速指明数据按指定字段进行排序

使用方法:

# 1、首先视图中设置filter_backends=[OrderingFilter]
# 2、然后再视图中添加 ordering_fields 属性,指定排序字段

from rest_framework.filters import OrderingFilter
class BooksView(ModelViewSet):
    queryset = Books.objects.all()
    serializer_class = BooksSerializer

    filter_backends = [OrderingFilter] # 第一步
    ordering_fields = ['price','id'] # 第二步
    
# http://127.0.0.1:8000/books/?ordering=id 通过ordering查看有无指明排序的字段,并通过字段来排序
# -id 表示针对id字段进行倒序排序
# id  表示针对id字段进行升序排序

三、分页

首先 Rest Framework 提供了三种分页方式,并且

  • PageNumberPagination
  • LimitOffsetPagination
  • CursorPagination

使用方式一:可以直接继承使用,但是配置参数需要在settings.py里面配置

使用方式二:通过子类继承父类分页器使用,直接在子类中修改父类的参数(推荐)

PageNumberPagination

子类中的属性:

  • page_size:每页数目
  • page_query_param:前端发送的页数关键字,默认“page”
  • page_size_query_param:前端发送每页数目关键字名,默认None
  • max_page_size:前端最多能设置的每页数量

如何使用:

from rest_framework.generics import ListAPIView
from rest_framework.pagination import PageNumberPagination
from app01.models import Books
from app01.ser import BooksSerializer

# 第一步:
class BookPageNumberPagination(PageNumberPagination):
    page_size = 3         # 每页条数
    page_query_param = 'page'   # 查询第几页的key
    page_size_query_param = 'size'  # 每一页显示的条数
    max_page_size = 5   # 每页最大条数


class BookView(ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BooksSerializer
    
    # 第二步:分页配置
    pagination_class = BookPageNumberPagination
    
    
# url:http://127.0.0.1:8000/books/?page=1&size=5 查询第1页,一共显示五条数据

LimitOffsetPagination

子类中的属性:

  • default_limit:默认限制,默认值与PAGE_SIZE设置一致
  • limit_query_param:limit参数名,默认'limit'
  • offset_query_param:offset参数名,默认'offset'
  • max_limit:最大limit限制,默认None

如何使用:

from rest_framework.generics import ListAPIView
from rest_framework.pagination import LimitOffsetPagination
from app01.models import Books
from app01.ser import BooksSerializer

# 第一步:
class BookLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 3           # 每页条数
    limit_query_param = 'limit'     # 往后拿几条
    offset_query_param = 'offset'   # 从第几条往后拿几条的标杆
    max_limit = 5       # 每页最大拿几条


class BookView(ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BooksSerializer
    
    # 第二步:分页配置
    pagination_class = BookLimitOffsetPagination
    
    
# url:http://127.0.0.1:8000/books/?limit=3&offset=4  从第三条开始往后拿4条数据

CursorPagination

子类中的属性:

  • cursor_query_param:默认查询字段,不需要修改
  • page_size:每页数目
  • ordering:按什么排序,需要指定

如何使用:

CursorPagination的查询速度快,但是却不能定位到第几页这样查,要么往前查,要么往后查。

from rest_framework.generics import ListAPIView
from rest_framework.pagination import CursorPagination
from app01.models import Books
from app01.ser import BooksSerializer

# 第一步:
class BookCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'   # 每页查询的key
    page_size = 3       # 每页显示条数
    ordering = 'id'    # 排序字段


class BookView(ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BooksSerializer
    
    # 第二步:分页配置
    pagination_class = BookCursorPagination
    
    
# url:http://127.0.0.1:8000/books/?cursor=cD0z

继承APIView使用方法

像方式一,方式二这样使用的话,就要视图类是继承 ListAPIView 然后直接配置就可以了

但是如果视图类继承的是 GenericAPIView 或者 APIView 的话,就需要用另一种方式了:

使用方法:

# 1、定义一个分页器
class BookPageNumberPagination(PageNumberPagination):
    page_size = 3         # 每页条数
    page_query_param = 'page'   # 查询第几页的key
    page_size_query_param = 'size'  # 每一页显示的条数
    max_page_size = 5   # 每页最大条数


class BookView(APIView):

    def get(self, request, *args, **kwargs):
        book_list = Books.objects.all()

        # 2、实例化得到一个分页器对象
        page_obj = BookPageNumberPagination()
        
        # 3、调用paginate_queryset返回每一页的数据
        book_list = page_obj.paginate_queryset(book_list, request, view=self)

        # 4、获取上一页下一页链接
        next_url = page_obj.get_next_link()
        previous_url = page_obj.get_previous_link()

        # 5、序列化
        book_ser = BooksSerializer(book_list, many=True)
        
        # 6、加入响应信息中
        data = {'next_url': next_url, 'previous_url': previous_url, 'data': book_ser.data}
        return Response(data=data)

四、异常处理

异常处理主要是用来统一接口返回

源码分析

异常处理在APIView的api_settings已经配置好了

'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',

def exception_handler(exc, context):
    # 先判断是不是404
    if isinstance(exc, Http404): # exc是异常信息的异常对象
        exc = exceptions.NotFound()
    # 然后判断是不是权限的问题
    elif isinstance(exc, PermissionDenied):
        exc = exceptions.PermissionDenied()  # 比如权限问题会返回一个字典
        
 # 在判断你抛出的是不是API的异常——>认证权限这些都是继承了API的异常
    if isinstance(exc, exceptions.APIException):
        headers = {}
        if getattr(exc, 'auth_header', None):
            headers['WWW-Authenticate'] = exc.auth_header
        if getattr(exc, 'wait', None):
            headers['Retry-After'] = '%d' % exc.wait

        if isinstance(exc.detail, (list, dict)):
            data = exc.detail
        else:
            data = {'detail': exc.detail}

        set_rollback()
        return Response(data, status=exc.status_code, headers=headers)
    # 只要是上面这些异常都做了处理
   

    return None  # 意味有些异常它没有处理,就会交给Django自己处理

如何处理

因为dir有些异常它不做处理,Django处理的又不符合我们的标准,所以就要写一个统一的异常类来替换掉它,把所有情况都处理,只要前端出异常看到的都是固定的东西。

如何写:

重写一个类,和它基本上差不多,配置的时候在 settings.py 里面全局配置

#  app01_auth.py
from rest_framework.views import exception_handler
from rest_framework.response import Response

def app01_exception_handler(exc, context):
    response = exception_handler(exc, context)  # 原来的drf处理的我们也需要
    # 两种情况,一个是None,drf没有处理,Django处理了,但是处理的不符合需求
    # response对象,drf处理了我们需要的


    if not response:
        # 如果没处理,那么我们自己处理
        return Response(data={'status': 400, 'error': str(exc)}, status=400)
    else:
        # drf 处理了,那么取出它处理的信息,重新处理一下
        return Response(data={'status': 400, 'error': response.data.get('detail')}, status=400)

然后再全局配置一下:settings.py

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'app01.app_auth.app01_exception_handler',
}

五、封装Response对象

class APIResponse(Response):
    def __init__(self,code=100,msg='成功',data=None,status=None,headers=None,**kwargs):
        
        dic = {'code': code, 'msg': msg}
        
        if  data:
            dic = {'code': code, 'msg': msg,'data':data}
            
        dic.update(kwargs)
        
        super().__init__(data=dic, status=status,headers=headers)
        
        
# 使用
return APIResponse(data={"name":'xiaoyang'},token='dsafsdfa',aa='dsafdsfdee')
return APIResponse(data={"name":'xiaoyang'})
return APIResponse(code='101',msg='错误',data={"name":'xiaoyang'},token='dsafsdfa',aa='dsafdsfdee',header={})

总结

到此这篇关于DRF过滤排序分页异常处理的文章就介绍到这了,更多相关DRF过滤排序分页内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • Python中bisect模块与堆操作详解

    Python中bisect模块与堆操作详解

    在Python中,bisect和heapq都是处理有序序列的常见模块,这篇文章将分别介绍这两个模块的用法和实现方式,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-06-06
  • 详解Flask数据库的连接与使用

    详解Flask数据库的连接与使用

    这篇文章主要为大家想想介绍了Python中Flask数据库的连接与使用,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以学习一下
    2023-02-02
  • Python真题案例之错位键盘 单词长度 字母重排详解

    Python真题案例之错位键盘 单词长度 字母重排详解

    这篇文章主要介绍了python实操案例练习,本文给大家分享的案例中主要任务有错位键盘、单词长度、字母重排,需要的小伙伴可以参考一下
    2022-03-03
  • python编程scrapy简单代码实现搜狗图片下载器

    python编程scrapy简单代码实现搜狗图片下载器

    这篇文章主要为大家介绍了使用python scrapy简单代码实现搜狗图片下载器示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-11-11
  • 详解python实现简单区块链结构

    详解python实现简单区块链结构

    区块链是一种数据结构,也是一个分布式数据库。这篇文章主要介绍了python实现简单区块链结构的相关知识,需要的朋友可以参考下
    2021-04-04
  • NumPy排序的实现

    NumPy排序的实现

    这篇文章主要介绍了NumPy排序的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • Python 使用with上下文实现计时功能

    Python 使用with上下文实现计时功能

    with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。这篇文章主要介绍了Python 使用with上下文实现计时,需要的朋友可以参考下
    2018-03-03
  • 详解python OpenCV学习笔记之直方图均衡化

    详解python OpenCV学习笔记之直方图均衡化

    本篇文章主要介绍了详解python OpenCV学习笔记之直方图均衡化,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • Django 配置多站点多域名的实现步骤

    Django 配置多站点多域名的实现步骤

    这篇文章主要介绍了Django 配置多站点多域名的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • 基于python实现高速视频传输程序

    基于python实现高速视频传输程序

    这篇文章主要介绍了基于python实现高速视频传输程序的实例代码,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05

最新评论