DRF从入门到精通六(排序组件、过滤组件、分页组件、异常处理)

文章目录

  • 一、排序组件
    • 继承GenericAPIView使用DRF内置排序组件
    • 继承APIView编写排序
  • 二、过滤组件
    • 继承GenericAPIView使用DRF内置过滤器实现过滤
    • 使用第三方模块django-filter实现and关系的过滤
    • 自定制过滤类
    • 排序搭配过滤使用
  • 三、分页组件
    • 分页器一:Pagination(基本分页)
    • 分页器二:LimitOffsetPagination(偏移分页)
    • 分页器三:CursorPagination(游标分页)
  • 四、异常处理

一、排序组件

一般涉及到了查询所有才有排序,对于表模型查询所有数据时需要根据某个字段进行排序时,我们就可以使用到REST framework提供的内置排序组件OrderingFilter来帮助我们快速指名数据按照指定字段进行排序

使用方法

  1. 导入DRF内置排序组件:from rest_framework.filters import OrderingFilter
  2. 在视图类中设置类属性:filter_backends=[OrderingFilter]
    注意这里能使用这个类属性,只有是继承了GenericAPIView才行。否则无法使用
    所以像继承APIView则无法使用内置过滤器
  3. REST framework会在请求的查询字符串参数中检查是否包含了ordering参数
  4. 如果包含了ordering参数,则按照ordering参数指明排序字段对数据集进行排序
  5. 前端可以传递的ordering参数的可选字段值需要再ordering_fields中指明

继承GenericAPIView使用DRF内置排序组件

	'需要有表数据,我这里直接沿用上一篇博客中的使用,然后使用自动生成路由的方式'
	from rest_framework.generics import ListAPIView
	from rest_framework.viewsets import ViewSetMixin
	from rest_framework.filters import OrderingFilter
	from .serializer import BookSerializer
	from . import models

	class BookView(ViewSetMixin,ListAPIView):
	    queryset = models.Book.objects.all()
	    serializer_class = BookSerializer
	    
	    '配置属性'
	    filter_backends = [OrderingFilter]
	    '必须指定表模型数据字段'
	    ordering_fields = ['price'] # 可以写多个排序字段
	    # ordering_fields = ['price','id']
	    
	    '127.0.0.1:8000/api/v2/books/?ordering=-price 倒序'
	    '127.0.0.1:8000/api/v2/books/?ordering=price 升序'

在这里插入图片描述


继承APIView的是使用不了以上DRF提供的排序组件,需要自己写,自己从请求地址中取出排序规则,然后自己排序

继承APIView编写排序

	from rest_framework.views import APIView
	from rest_framework.response import Response
	from rest_framework.viewsets import ViewSetMixin
	from rest_framework.mixins import ListModelMixin
	
	'这里我还是沿用上面自动生成路由的方式,所以需要配置ViewSetMixin'
	
	class BookView(ViewSetMixin, APIView, ListModelMixin):
		'由于是APIView需要自己重写list方法,在自动生成路由中是get:list'
	    def list(self, request, *args, **kwargs):
	        '从地址栏中取出过滤条件'
	        print(request.query_params)  # ?ordering=-price,id
	        query_params = request.query_params  # {ordering:price}
	        '''支持多个条件排序ordering=-price,id'''
	        # try:
	        '127.0.0.1:8000/api/v2/books/?ordering=-price,id'
	        if ',' in query_params.get('ordering'):
	            query = query_params.get('ordering').split(',')
	            book_list = models.Book.objects.all().order_by(*query)
	        else:
	            book_list = models.Book.objects.all().order_by(query_params.get('ordering'))
	
	        ser = BookSerializer(instance=book_list, many=True)
	        return Response(ser.data)

在这里插入图片描述


二、过滤组件

restful规范中,要求请求地址中带过滤条件,五个接口中,只有查询所有接口需要过滤和排序。

其实上面排序使用的就是DRF内置过滤器,因为排序本就是过滤的一种特殊情况,所以这里就不在过多介绍了

继承GenericAPIView使用DRF内置过滤器实现过滤

	from rest_framework.filters import SearchFilter
	from rest_framework.viewsets import ViewSetMixin
	from rest_framework.generics import ListAPIView
	from rest_framework.filters import OrderingFilter,SearchFilter
	
	class BookView(ViewSetMixin, GenericAPIView, ListModelMixin):
	    queryset = models.Book.objects.all()
	    serializer_class = BookSerializer
	    'SearchFilter,使用的是模糊匹配'
	    filter_backends = [SearchFilter]
	    
	    '''只能填写表中字段'''
	    search_fields = ['name']
	    search_fields = ['name','price']  可多字段过滤
	    # 127.0.0.1:8000/api/v2/books/?search=东
	    # 127.0.0.1:8000/api/v2/books/?search=46  
	    '因为是多字段过滤,并且SearchFilter是模糊匹配,所以如果多字段中有一样的东西,如1都会被查到'

使用DRF内置过滤器,它搜索结果的关系为or(或)的关系,不是and关系。并且只能是使用关键字search才能使用,如果我们想要用name=东&price=66这种方式的得使用别的方法来实现

在这里插入图片描述


使用第三方模块django-filter实现and关系的过滤

	'首先需要安装第三方模块:pip install django-filter'
	from django_filters.rest_framework import DjangoFilterBackend
	from rest_framework.viewsets import ViewSetMixin
	from rest_framework.generics import ListAPIView
	'使用这个第三方模块可以实现and关系,并且只能是精准匹配。并且暂不支持or关系'
	class BookView(ViewSetMixin,ListAPIView):
	    queryset = models.Book.objects.all()
	    serializer_class = BookSerializer
	    
	    filter_backends = [DjangoFilterBackend]
	    filterset_fields = ['name', 'price']
	    # 127.0.0.1:8000/api/v2/books/?name=东游记&price=46 精准匹配
	    '但是对于django-filter来讲它是支持扩写的,所以是可以支持模糊匹配,具体操作自寻查找'

在这里插入图片描述

使用这个django-filter还是有局限性的,无法实现or关键以及模糊匹配,那么我们可以使用自定制过滤类


自定制过滤类

	使用步骤:
		1.定义一个过滤类,并且继承BaseFilterBackend
		2.重写filter_queryset方法,并且在内部完成过滤规则
		3.在视图类中配置自定义的过滤类

	from rest_framework.filters import BaseFilterBackend
	class CommonFilter(BaseFilterBackend):
	    def filter_queryset(self, request, queryset, view):
	        '''queryset是之前所有数据,models.Book.object.all()'''
	        # request是当次请求
	        # query_params = request.query_params
	        '方式一:'
			name = request.query_params.get('name',None)
	        price = request.query_params.get('price',None)
	        res = queryset.filter(name__contains=name,price=price)
	        
			'方式二:'
	        if request.query_params.get('name'):
            	queryset = queryset.filter(name__contains=request.query_params.get('name'))
	        if request.query_params.get('price'):
	            '支持链式调用'
	            queryset = queryset.filter(price=request.query_params.get('price'))
	        return queryset  # 这里返回过滤后的对象 res

	
   	from .filters import CommonFilter  
	class BookView(ViewSetMixin,ListAPIView):
	    queryset = models.Book.objects.all()
	    serializer_class = BookSerializer
	    '无需再配置字段了,因为在自定制类中已经写好了过滤规则,所以在视图类中无需配置'
	    filter_backends = [CommonFilter]
	    # 127.0.0.1:8000/api/v2/books/?name=游记&price=666
	    '这样就实现了模糊匹配name字段并且精准匹配price字段,以及查询单个字段的规则'

在这里插入图片描述


排序搭配过滤使用

	from .filters import CommonFilter  # 使用的是上面的自定制过滤类
	from rest_framework.filters import OrderingFilter
	class BookView(ViewSetMixin,ListAPIView):
	    queryset = models.Book.objects.all()
	    serializer_class = BookSerializer
	    filter_backends = [OrderingFilter,CommonFilter]  # 排序加过滤,从左到右依次执行
	    ordering_fields = ['price','id']

在这里插入图片描述


三、分页组件

分页只针对查询所有的接口,其他四个接口不需要分页。drf内置了三个分页器,对应三种分页方式,内置的分页类不能直接使用,需要继承,定制一些参数后才能使用。一个接口只能有一种分页方式,不能混合分页方式

分页器一:Pagination(基本分页)

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

	from rest_framework.pagination import PageNumberPagination

	class CommonPageNumberPagination(PageNumberPagination):
	    page_size = 3 # 默认每页显示的条数
	    page_query_param = 'page' # 使用该关键字指定页码(客户端使用)
	
	    page_size_query_param = 'size' # 通过该关键字可以手动指定页面显示的数据条数(客户端使用)
	
	    max_page_size = 5 # 只针对客户端手动指定页面显示的数据条数做出一个限制,但不影响page_size属性。

视图类

	'导入配置的分页类'
	from .pagination import CommonPageNumberPagination
	
	from rest_framework.viewsets import ViewSetMixin
	from rest_framework.generics import ListAPIView
	from . import models
	from .serializer import BookSerializer
	from .filters import CommonFilter
	from rest_framework.filters import OrderingFilter
	
	class BookView(ViewSetMixin,ListAPIView):
	    queryset = models.Book.objects.all()
	    serializer_class = BookSerializer
	    '注意分页方式一个接口只能使用一种,所以没有加中括号'
	    pagination_class = CommonPageNumberPagination
	    '''使用分页并不影响排序和过滤'''
	    filter_backends = [OrderingFilter,CommonFilter]
	    filterset_fields = ['name', 'price']

	# 127.0.0.1:8000/api/v2/books/?page=2
	# 127.0.0.1:8000/api/v2/books/
	# 127.0.0.1:8000/api/v2/books/?page=2&size=3

在这里插入图片描述

响应时额外携带了3个参数,分别是:

  1. count:book接口的数据总量
  2. next:下一页的URL
  3. previous:上一页的URL,如果没有上一页返回None

当然,我们也可以手动指定页面显示的条数,根据page_size_query_param属性值来作为关键字。

在这里插入图片描述

可以看到我们需要显示的是6条数据,而后端只响应了5条,这是因为max_page_size属性值的作用:限制了客户端手动获取数据时最大返回的数据条数。


分页器二:LimitOffsetPagination(偏移分页)

偏移分页,该分页组件作用是:从哪一条数据之后开始显示,以及制定数据显示的条数

前端访问形式:http://127.0.0.1:8080/book/?offset=2&limit=4,这表示从第3条数据之后显示4条数据

自定义分页类

	from rest_framework.pagination import LimitOffsetPagination
	
	class CommonLimitOffsetPagination(LimitOffsetPagination):
		# 等同于上面的:page_size
	    default_limit = 2  # 如果前端没有手动指定获取的数据条数时,使用该属性值
	
	    limit_query_param = 'limit'  # 前端通过该关键字指定数据条数
	    '每页显示条数,查询的条数  例子 ?limit=100 意思就是每页显示100条,如果不传应用default_limit的参数'
	
	    offset_query_param = 'offset'  # 通过该关键字指定从哪条数据之后开始获取数据
	    '偏移量  举个例子offset=6&limit=30  意思就是从第6条开始,拿30条'
	    
	    # 等同于上面的:max_page_size
	    max_limit = 5  # 只限制limit_query_param能够获取的最大数据条数,而不影响default_limit

视图类

	'导入配置的分页类'
	from .pagination import CommonPageNumberPagination
	
	class BookView(ViewSetMixin,ListAPIView):
	    queryset = models.Book.objects.all()
	    serializer_class = BookSerializer
	    '注意分页方式一个接口只能使用一种,所以没有加中括号'
	    pagination_class = CommonPageNumberPagination

		# http://127.0.0.1:8000/api/v2/books/?limit=6&offset=2  从第2条开始拿6条

在这里插入图片描述

从第二条数据之后开始指定获取数据的条数,使用了limit指定了获取6条,但是被max_limit=5给限制了,所以后端只能返回2条数据,如果不使用limit指定获取的数据条数,那么默认使用default_limit=2后端会返回2条数据。


分页器三:CursorPagination(游标分页)

自定义分页类

	from rest_framework.pagination import CursorPagination
	class CommonCursorPagination(CursorPagination):
	    cursor_query_param = 'cursor'  # 按游标查询的查询条件,value值前端是不知道的,只能通过后台返回
	    page_size = 2  # 每页显示多少条啊
	    ordering = 'id'  # 排序规则,必须是表中的字段

视图类

	from .pagination import CommonCursorPagination
	class BookView(ViewSetMixin,ListAPIView):
	    queryset = models.Book.objects.all()
	    serializer_class = BookSerializer
	    '注意分页方式一个接口只能使用一种,所以没有加中括号'
	    '另外使用游标分页的方式后就不能再其中使用排序了,因为其内部已经排好序了'
	    pagination_class = CommonCursorPagination
	   '并且只能选择上一页和下一页,不能指定跳转某一页,但是速度快,针对与特别大的数据量,游标分页有优势'

在这里插入图片描述


四、异常处理

REST framework提供了异常处理,我们可以自定义异常处理函数。主要是为了DRF在运行过程中发生的错误进行一个捕获,然后响应友好的提示信息给前端。

自定义异常处理函数:(定制一个异常处理统一的返回格式)

	from rest_framework.views import exception_handler,Response
	# drf的异常处理是exception_handler处理了,到那时没处理非drf的异常
	# 自己写个函数,处理drf异常和自己的异常,以后只要是出了异常都会走这里
	def Common_exception_handler(exc, context):
	    # exc:异常信息
	    # context:执行请求的视图、args、kwargs参数、request请求
	
	    res = exception_handler(exc, context)
	
	    # 在此处补充自定义的异常处理
	    if res:  # 有值说明是drf的异常,如果没有值说明是自己的异常
	        # data = {'detail': exc.detail}
	        detail = res.data.get('detail') or "drf异常,请联系系统管理员"
	        return Response({'code':666,'message':detail})
	    else:
	        return Response({'code':777,'message':f"系统异常,请联系管理{str(exc)}"})

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

	REST_FRAMEWORK = {
	    'EXCEPTION_HANDLER': 'appo1.exception.Common_exception_handler',
	}

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

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

视图类

	'''全局异常处理'''
	from rest_framework.exceptions import AuthenticationFailed,APIException
	'''
	Drf中无论在三大认证还是视图类中 方法执行报错包括主动抛异常
	都会执行一个函数excption_exception处理异常的函数
	只要出了异常APIView的dispatch中就可以捕获到 
	执行配置文件中的'EXCEPTION_HANDLER':'rest_framework.views.exception_handler'
	'''
	class UserView(ViewSetMixin, APIView):
	    def create(self, request):
	        raise Exception('你出错了')
	
	        # drf默认能处理自己的异常,它的异常都是继承自APIException的异常
	        # raise AuthenticationFailed('认证失败')
	        return Response({'code':100,'msg':'1111'})

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/276365.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity 创建/删除/启用/禁用组件的惯用方法

1、创建组件&#xff1a; Unity 创建组件可以通过编辑器中的"Add Component"创建&#xff0c;或者代码动态创建&#xff1a;GameObject.AddComponent<T>()&#xff0c;如&#xff1a; ameObject.AddComponent<Rigidbody>(); 2、删除组件&#xff1a; …

中介者模式-Mediator Pattern-1

如果在一个系统中对象之间的联系呈现为网状结构&#xff0c; 对象之间存在大量的多对多联系&#xff0c;将导致系统非常复杂。 这些对象既会影响别的对象&#xff0c;也会被别的对象所影响。 这些对象称为同事对象&#xff0c;它们之间通过彼此的相互作用实现系统的行为。 在网…

同义词替换降低论文相似度的注意事项 papergpt

大家好&#xff0c;今天来聊聊同义词替换降低论文相似度的注意事项&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff0c;可以借助此类工具&#xff1a; 标题&#xff1a;同义词替换降低论文相似度的注意事项 …

【Java系列】多线程案例学习——基于阻塞队列实现生产者消费者模型

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Java系列专栏】【JaveEE学习专栏】 本专栏旨在分享学习JavaEE的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录…

案例260:基于微信小程序的签到系统的设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder …

git 常用命令总结

git 工作原理图&#xff1a; git 常用命令及解释: 命令解释例子git init在当前目录初始化一个新的 Git 仓库。git initgit clone <repository>克隆一个远程仓库到本地。git clone https://github.com/example/repository.gitgit add <file>将文件的变化添加到暂存…

分享44个PyQt5源码总有一个是你想要的

分享44个PyQt5源码总有一个是你想要的 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 链接&#xff1a;https://pan.baidu.com/s/1_5H_0Ydg0XUa1fz5Jok51Q?pwd6666 提取码&#xff1a;6666 项目名称 B站直播弹幕姬&#xff…

哪种猫粮比较好?怎样囤性价比高的主食冻干品牌 ?

在过去的100多年里&#xff0c;猫咪主食市场一直被膨化猫粮主导。然而&#xff0c;随着猫咪频频出现猝死、失明、发育不良以及营养不良等问题&#xff0c;猫主人们开始质疑膨化粮是否最适合猫咪。于是&#xff0c;从上世纪90年代开始&#xff0c;出现了生骨肉喂养。生骨肉确实是…

XV7081BB陀螺仪传感器

XV7081BB是一款用于自动化机器的数字输出型陀螺仪传感器&#xff0c;具有卓越的性能&#xff0c;尤其是偏置输出稳定性和低噪声。特点如下&#xff1a; 优良的偏置温度系数为0.0024(/s)/C。 ●低角度随机游走0.065/√h ●SPI/IC串行接口 集成的用户可选择的数字滤波器 ●角…

E : DS查找—二叉树平衡因子

Description 二叉树用数组存储&#xff0c;将二叉树的结点数据依次自上而下,自左至右存储到数组中&#xff0c;一般二叉树与完全二叉树对比&#xff0c;比完全二叉树缺少的结点在数组中用0来表示。 计算二叉树每个结点的平衡因子&#xff0c;并按后序遍历的顺序输出结点的平衡…

mybatisX自动生成sql语句,尝试测试方法报错

今天我使用mybatisx自定义mapper方法生成sql语句后&#xff0c;在测试时报错 错误是MyBatis 无法找到映射的语句&#xff08;Statement&#xff09;引起的 我是这样操作的&#xff0c;在mapper接口自定义了一个方法 然后alt加enter&#xff0c;自动生成sql 结果 mapper.xml文件…

31.Java程序设计-基于Springboot的鲜花商城系统的设计与实现

引言 背景介绍&#xff1a;鲜花商城系统的兴起和发展。研究目的&#xff1a;设计并实现一个基于Spring Boot的鲜花商城系统。论文结构概述。 文献综述 回顾相关鲜花商城系统的设计与实现。分析不同系统的优缺点。强调Spring Boot在系统设计中的优越性。 系统设计 需求分析 用户…

css中sprite(css精灵)是什么,有什么优缺点

概念 将多个小图片拼接到一个图片中 。通过 background-position 和元素尺寸调节需要显示的背景图案。 优点 减少 HTTP 请求数&#xff0c;极大地提高页面加载速度 增加图片信息重复度&#xff0c;提高压缩比&#xff0c;减少图片大小 更换⻛格方便&#xff0c; 只需在一张或…

mysql保姆安装教程

一.下载install文件 1.进入Mysql官网&#xff0c;点击下载 2.选择MySQL Installer for Windows 3.推荐选择第二个安装包 4.不登陆&#xff0c;开始下载 5.等待下载完成 二.安装前的配置 通过电脑“设置”&#xff0c;检查电脑是否包含中文名&#xff0c;如果包含请重命名 …

生活常识-如何开社保证明(四川)

下载并打开天府市民云APP 注册后登陆 点击社保服务 点击社保证明 点击【四川省社会保险个人社保证明名(近24个月)】 点击下载 下载后点击【QQ发送给好友&#xff0c;然后发送给自己的电脑设备(我的电脑)】

通过C++程序实现光驱的自动化刻录和读取

文章目录 ISO文件格式光盘的基本概念光盘种类特点DVDR光盘使用windows调用Linux调用Linux平台下用到的C库:读取设备驱动列表向光驱中写文件 数字存储媒体快速发展的今天&#xff0c;光驱的使用已经不像以前那样普及了。但是在数据备份、安装软件和操作系统、旧设备兼容等领域还…

LTPI协议的理解——LTPI协议的定义和结构

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 LTPI协议的理解——LTPI协议的定义和结构 定义DC-SCM 2.0 LTPI 结构GPIO通道I2C/SMBus通道Uart通道OEM通道数据通道 总结 定义 LTPI (LVDS Tunneling Protocol & Interf…

算法基础之计数问题

计数问题 核心思想&#xff1a; 数位dp / 累加 累加 ​ 分情况讨论 &#xff1a; xxx 000 ~ abc –1 yyy 000 ~ 999 共 abc * 1000 种 特别地&#xff0c;当枚举数字0时 (找第4位为0的数) 前三位不能从000开始了 否则没这个数不合法(有前导零) xxx abc 2.1. d < 1 , 不…

拥抱健康,远离内耗:程序员必备的情绪管理策略

程序员是一群特别脆弱的群体&#xff0c;俗称IT民工&#xff01; 每天上班要跟产品斗智斗勇&#xff0c;还要跟bug斗的难解难分&#xff0c;另外还要被领导批&#xff0c;跟同事扯皮&#xff0c;整个一天下来常常筋疲力尽。 程序员大多不善言语&#xff0c;受了委屈往往喜欢吞到…

抓包工具Charles安装及使用

Charles 介绍 Charles 是在 Mac 下常用的网络封包截取工具&#xff0c;在做 移动开发时&#xff0c;我们为了调试与服务器端的网络通讯协议&#xff0c;常常需要截取网络封包来分析。 Charles 通过将自己设置成系统的网络访问代理服务器&#xff0c;使得所有的网络访问请求都…
最新文章