当前位置: 首页 > news >正文

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

一 过滤Filtering

对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。

pip install django-filter

在配置文件中增加过滤后端的设置:

INSTALLED_APPS = [...'django_filters',  # 需要注册应用,
]REST_FRAMEWORK = {...'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}

在视图中添加filter_fields属性,指定可以过滤的字段

class StudentListView(ListAPIView):queryset = Student.objects.all()serializer_class = StudentSerializerfilter_fields = ('age', 'sex')# 127.0.0.1:8000/four/students/?sex=1

二 排序

对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。

使用方法:

在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。

前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。

示例:

class StudentListView(ListAPIView):queryset = Student.objects.all()serializer_class = StudentModelSerializerfilter_backends = [OrderingFilter]ordering_fields = ('id', 'age')# 127.0.0.1:8000/books/?ordering=-age
# -id 表示针对id字段进行倒序排序
# id  表示针对id字段进行升序排序

如果需要在过滤以后再次进行排序,则需要两者结合!

from rest_framework.generics import ListAPIView
from students.models import Student
from .serializers import StudentModelSerializer
from django_filters.rest_framework import DjangoFilterBackend
class Student3ListView(ListAPIView):queryset = Student.objects.all()serializer_class = StudentModelSerializerfilter_fields = ('age', 'sex')# 因为局部配置会覆盖全局配置,所以需要重新把过滤组件核心类再次声明,# 否则过滤功能会失效filter_backends = [OrderingFilter,DjangoFilterBackend]ordering_fields = ('id', 'age')

三 分页Pagination

REST framework提供了分页的支持。

我们可以在配置文件中设置全局的分页方式,如:

REST_FRAMEWORK = {'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination','PAGE_SIZE': 100  # 每页数目
}

也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_clas属性来指明。

class LargeResultsSetPagination(PageNumberPagination):page_size = 1000page_size_query_param = 'page_size'max_page_size = 10000
class BookDetailView(RetrieveAPIView):queryset = BookInfo.objects.all()serializer_class = BookInfoSerializerpagination_class = LargeResultsSetPagination

注意:如果在视图内关闭分页功能,只需在视图内设置

pagination_class = None

可选分页器

1) 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 前端最多能设置的每页数量
# APIView
from rest_framework.pagination import PageNumberPagination
# 一 基本使用:url=url=http://127.0.0.1:8000/pager/?page=2&size=3,size无效
class  Pager(APIView):def get(self,request,*args,**kwargs):# 获取所有数据ret=models.Book.objects.all()# 创建分页对象page=PageNumberPagination()# 在数据库中获取分页的数据page_list=page.paginate_queryset(ret,request,view=self)# 对分页进行序列化ser=BookSerializer1(instance=page_list,many=True)return Response(ser.data)
# 二 自定制 url=http://127.0.0.1:8000/pager/?page=2&size=3
# size=30,无效,最多5条
class Mypage(PageNumberPagination):page_size = 2page_query_param = 'page'# 定制传参page_size_query_param = 'size'# 最大一页的数据max_page_size = 5
class  Pager(APIView):def get(self,request,*args,**kwargs):# 获取所有数据ret=models.Book.objects.all()# 创建分页对象page=Mypage()# 在数据库中获取分页的数据page_list=page.paginate_queryset(ret,request,view=self)# 对分页进行序列化ser=BookSerializer1(instance=page_list,many=True)# return Response(ser.data)# 这个也是返回Response对象,但是比基本的多了上一页,下一页,和总数据条数(了解即可)return page.get_paginated_response(ser.data)#ListAPIView# 声明分页的配置类
from rest_framework.pagination import PageNumberPagination
class StandardPageNumberPagination(PageNumberPagination):# 默认每一页显示的数据量page_size = 2# 允许客户端通过get参数来控制每一页的数据量page_size_query_param = "size"max_page_size = 10# 自定义页码的参数名page_query_param = "p"class StudentAPIView(ListAPIView):queryset = Student.objects.all()serializer_class = StudentModelSerializerpagination_class = StandardPageNumberPagination# 127.0.0.1/four/students/?p=1&size=5

2)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
# APIView
# http://127.0.0.1:8000/pager/?offset=4&limit=3
from rest_framework.pagination import LimitOffsetPagination
# 也可以自定制,同简单分页
class  Pager(APIView):def get(self,request,*args,**kwargs):# 获取所有数据ret=models.Book.objects.all()# 创建分页对象page=LimitOffsetPagination()# 在数据库中获取分页的数据page_list=page.paginate_queryset(ret,request,view=self)# 对分页进行序列化ser=BookSerializer1(instance=page_list,many=True)# return page.get_paginated_response(ser.data)return Response(ser.data)
#ListAPIView
from rest_framework.pagination import LimitOffsetPagination
class StandardLimitOffsetPagination(LimitOffsetPagination):# 默认每一页查询的数据量,类似上面的page_sizedefault_limit = 2limit_query_param = "size"offset_query_param = "start"class StudentAPIView(ListAPIView):queryset = Student.objects.all()serializer_class = StudentModelSerializer# 调用页码分页类# pagination_class = StandardPageNumberPagination# 调用查询偏移分页类pagination_class = StandardLimitOffsetPagination

3)CursorPagination

前端访问网址形式:

GET http://127.0.0.1/four/students/?cursor=cD0xNQ%3D%3D

可以在子类中定义的属性:

  • cursor_query_param:默认查询字段,不需要修改
  • page_size:每页数目
  • ordering:按什么排序,需要指定
#APIView
from rest_framework.pagination import CursorPagination
# 看源码,是通过sql查询,大于id和小于id
class  Pager(APIView):def get(self,request,*args,**kwargs):# 获取所有数据ret=models.Book.objects.all()# 创建分页对象page=CursorPagination()page.ordering='nid'# 在数据库中获取分页的数据page_list=page.paginate_queryset(ret,request,view=self)# 对分页进行序列化ser=BookSerializer1(instance=page_list,many=True)# 可以避免页码被猜到return page.get_paginated_response(ser.data)
# ListAPIView
class MyCursorPagination(CursorPagination):page_size=2ordering='-id'
from rest_framework.generics import ListAPIView
class AuthorListView(ListAPIView):serializer_class = serializers.AuthorModelSerializerqueryset = models.Author.objects.filter(is_delete=False)pagination_class =MyCursorPagination

应用

from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
class MyPageNumberPagination(PageNumberPagination):page_size = 2page_query_param = 'page'# 定制传参page_size_query_param = 'size'# 最大一页的数据max_page_size = 5class MyLimitOffsetPagination(LimitOffsetPagination):default_limit = 2# 最大一页的数据max_limit = 5
class MyCursorPagination(CursorPagination):page_size=2ordering='-id'
from rest_framework.generics import ListAPIView
class AuthorListView(ListAPIView):serializer_class = serializers.AuthorModelSerializerqueryset = models.Author.objects.filter(is_delete=False)pagination_class =MyCursorPagination

四 异常处理 Exceptions

REST framework提供了异常处理,我们可以自定义异常处理函数。

4.1 使用方式

from rest_framework.views import exception_handlerdef custom_exception_handler(exc, context):# 先调用REST framework默认的异常处理方法获得标准错误响应对象response = exception_handler(exc, context)# 在此处补充自定义的异常处理if response is None:response.data['status_code'] = response.status_codereturn response

在配置文件中声明自定义的异常处理

REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}

如果未声明,会采用默认的方式,如下

rest_frame/settings.py

REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}

4.2 案例

补充上处理关于数据库的异常

from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework import status
from django.db import DatabaseErrordef exception_handler(exc, context):response = drf_exception_handler(exc, context)if response is None:view = context['view']print('[%s]: %s' % (view, exc))if isinstance(exc, DatabaseError):response = Response({'detail': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)else:response = Response({'detail': '未知错误'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)return response# 在setting.py中配置
REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'app01.ser.exception_handler'
}

4.3 REST framework定义的异常

  • APIException 所有异常的父类
  • ParseError 解析错误
  • AuthenticationFailed 认证失败
  • NotAuthenticated 尚未认证
  • PermissionDenied 权限决绝
  • NotFound 未找到
  • MethodNotAllowed 请求方式不支持
  • NotAcceptable 要获取的数据格式不支持
  • Throttled 超过限流次数
  • ValidationError 校验失败

也就是说,很多的没有在上面列出来的异常,就需要我们在自定义异常中自己处理了。

作者:liuqingzheng

相关文章:

  • Prometheus-JVM
  • Airtest+Poco多设备并发自动化游戏测试框架(遇到的问题)
  • 【NI-RIO入门】理解Windows、Real Time与FPGA之间数据通信的原理
  • 【VTK-Rendering::Annotation】第一期 vtkCaptionActor2D
  • 微服务实战系列之Dubbo(上)
  • 开集目标检测-标签提示目标检测大模型(吊打YOLO系列-自动化检测标注)
  • 【虹科分享】利用ProfiShark 构建便携式网络取证工具包
  • AtCoder Beginner Contest 334 G
  • 用Python处理PDF:拆分与合并PDF文档
  • 大厂整理的23年前端工程师面试手册,高频面试题终结篇,github上标星16k!
  • 排序笔记总结
  • 2024深入评测CleanMyMac X4.14.6破解版新的功能
  • 微服务架构<2>
  • storyBook play学习
  • uni-app page新建以及page外观配置
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • export和import的用法总结
  • JS题目及答案整理
  • LeetCode算法系列_0891_子序列宽度之和
  • Linux链接文件
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • Solarized Scheme
  • 番外篇1:在Windows环境下安装JDK
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 聊聊flink的BlobWriter
  • 人脸识别最新开发经验demo
  • 三栏布局总结
  • 使用SAX解析XML
  • 数据仓库的几种建模方法
  • 学习使用ExpressJS 4.0中的新Router
  • 正则学习笔记
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • "无招胜有招"nbsp;史上最全的互…
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • (1)bark-ml
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (三)elasticsearch 源码之启动流程分析
  • (数据结构)顺序表的定义
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)http-server应用
  • (转)人的集合论——移山之道
  • (转)树状数组
  • ..回顾17,展望18
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .net core 控制台应用程序读取配置文件app.config
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • .vimrc php,修改home目录下的.vimrc文件,vim配置php高亮显示
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?
  • :如何用SQL脚本保存存储过程返回的结果集
  • @EnableWebMvc介绍和使用详细demo
  • @requestBody写与不写的情况
  • [android] 天气app布局练习