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

目录
  • 一、过滤
  • 二、排序
  • 三、分页
    • PageNumberPagination
    • LimitOffsetPagination
    • CursorPagination
    • 继承APIView使用方法
  • 四、异常处理
    • 源码分析
    • 如何处理
  • 五、封装Response对象
  • 总结

一、过滤

对于列表数据要通过字段来进行过滤,就需要添加 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过滤排序分页内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Django实现drf搜索过滤和排序过滤

    前言 当我们需要对后台的数据进行过滤的时候,drf有两种,搜索过滤和排序过滤. 搜索过滤:比如我们想返回sex=1的,那么我们就可以从所有数据中进行筛选 排序过滤:比如我们想对价格进行升序排列,就可以使用排序过滤 搜索过滤 在实际的使用过程中十分简单,只需要在视图类中配置一个全局变量filter_backends,然后在search_fields确定需要通过哪个字段进行筛选 from rest_framework.filters import SearchFilter class CarView

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

    目录 一.过滤 二.排序 三.分页 PageNumberPagination LimitOffsetPagination CursorPagination 继承APIView使用方法 四.异常处理 源码分析 如何处理 五.封装Response对象 总结 一.过滤 对于列表数据要通过字段来进行过滤,就需要添加 django-filter 模块 使用方法: # 1.注册,在app中注册 settings.py INSTALLED_APPS = [ 'django_filters', ] # 2.se

  • DataTables+BootStrap组合使用Ajax来获取数据并且动态加载dom的方法(排序,过滤,分页等)

    Datatables是一款jquery表格插件.它是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能. 主要功能 分页,即时搜索和排序 几乎支持任何数据源:DOM, javascript, Ajax 和 服务器处理 支持不同主题 DataTables, jQuery UI, Bootstrap, Foundation 各式各样的扩展: Editor, TableTools, FixedColumns -- 丰富多样的option和强大的API 支持国际化 超过2900+个单元测试 免

  • 生成多字段排序分页的SQL的通用类

    如果的单一字段排序分页,现在有很多的存储过程和SQL语句,分页的时候,只取pageSize的记录,可遇见的问题是: 这个单一字段必须是唯一的 这个字段必须是可以被排序的 不支持多字段排序 针对这一问题,我用C#做了一个类,解决以上的对多字段排序分页和每次都取pageSize条记录的问题 先看看代码:  复制代码 代码如下: using System;  using System.Collections.Specialized;  namespace web  {      /// <summar

  • 分页显示Oracle数据库记录的类之一

    <?php /********************************************* TOracleViewPagev 2.0 日期:2000-9-23 分页显示Oracle数据库记录的类 更新日期:2000-10-19 增加显示TopRecord的功能,允许第一页显示的记录数与其它页不同. 作者:sharetop email:ycshowtop@21cn.com ***********************************************/ class T

  • Python接单的过程记录分享

    一.需求介绍 该需求主要是分析彩票的历史数据,彩票的名称为: 1.极速飞艇 链接:https://www.dsn665.com/view/jisuft/pk10kai_history.html 2.极速赛车 链接:https://www.dsn665.com/view/jisusaiche/pk10kai.html 客户的需求是根据彩票的前两期的情况,如果存在某个斜着的两个数字相等,那么就买第三期的同一个位置处的彩票, 对于1.,如果相等的数字是:1-5,那就买6-10,如果相等的数字是:6-1

  • 深入浅析Python数据分析的过程记录

    目录 一.需求介绍 二.以第1.个为例进行数据分析 1.获取一天的数据 2.开始一天的数据的分析 3.循环日期进行多天的数据分析: 4.将数据写入Excel表格中 三.完整的代码展示: 总结 一.需求介绍 该需求主要是分析某一种数据的历史数据. 客户的需求是根据该数据的前两期的情况,如果存在某个斜着的两个数字相等,那么就买第三期的同一个位置处的彩票,对于1.,如果相等的数字是:1-5,那就买6-10,如果相等的数字是:6-10,那就买1-5:对于2.,如果相等的数字是:1-5,那就买1-5,如果

  • Django与DRF结合的全局异常处理方案详解

    目录 前言 实现的目标 DRF全局异常拦截的解决思路 Django异常处理方案 总结 前言 Django 和 DRF(django rest framawork) 的结合在 python 后台中经常出现的组合.对于异常的全局处理,我们系统能有一个统一的解决方案,在开发环境能看到比较全的异常堆栈,而在生产环境能更好的给用户一个友好的提示,本文旨在提出一个统一个全局异常处理方案,仅供参考使用. 实现的目标 如果没有 DRF,我们只需要在 Django 中加一个中间件就可以解决全局异常的处理问题,但是

  • Vue数组更新及过滤排序功能

    前面的话 Vue为了增加列表渲染的功能,增加了一组观察数组的方法,而且可以显示一个数组的过滤或排序的副本.本文将详细介绍Vue数组更新及过滤排序 变异方法 Vue 包含一组观察数组的变异方法,它们将会触发视图更新,包含以下方法 push() 接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度 pop() 从数组末尾移除最后一项,减少数组的length值,然后返回移除的项 shift() 移除数组中的第一个项并返回该项,同时数组的长度减1 unshift() 在数组前端添加任意个

  • Ubuntu 16.04安装微信的过程记录

    微信没有出Linux的版本,但是可以通过以下方式解决: 1.使用网页版,除了没有公众号之后,一切都没问题,包括传文件等. 网页登录地址:https://wx.qq.com/ 2.使用第三方版本,只不过这个是桌面应用,原理是通过网页API集成的,稳定性还是可以的. 网站:https://github.com/geeeeeeeeek/electronic-wechat/releases,离线版本:(链接: https://pan.baidu.com/s/1i5Dr15r 密码: rc93) 其实不用

  • vue中使用protobuf的过程记录

    由于目前公司采用了ProtoBuf做前后端数据交互,进公司以来一直用的是公司大神写好的基础库,完全不了解底层是如何解析的,一旦报错只能求人,作为一只还算有钻研精神的猿,应该去了解一下底层的实现,在这里记录一下学习过程. Protobuf简单介绍 Google Protocol Buffer(简称 Protobuf)是一种轻便高效的结构化数据存储格式,平台无关.语言无关.可扩展,可用于通讯协议和数据存储等领域. 有几个优点: 1.平台无关,语言无关,可扩展: 2.提供了友好的动态库,使用简单; 3

随机推荐