DRF 查询(排序、过滤、分页)

查询(排序、过滤、分页)

【0】准备

(1)Q查询

  • 详细内容可见:Django模型层-CSDN博客
  • Django 的 Q 对象提供了一种在数据库查询中构造复杂查询的方法。当你想在单个查询中组合多个过滤条件,并且这些条件之间不仅仅是简单的 AND 关系时,Q 对象就显得非常有用。
  • 导入:from django.db.models import Q
  • 简单示例:或与非
# 查找 name 字段为 'John' 或 age 字段大于 30 的对象  
MyModel.objects.filter(Q(name='lily') | Q(age__gt=30))
# 查找 name 字段为 'John' 并且 age 字段大于 30 的对象  
MyModel.objects.filter(Q(name='lily') & Q(age__gt=30))
# 查找 name 字段不是 'John' 的对象  
MyModel.objects.filter(~Q(name='lily'))

(2)数据准备

  • 模型表
from django.db import modelsclass Book(models.Model):name = models.CharField(max_length=64, verbose_name="书名")price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="价格")publish_name = models.CharField(max_length=64, verbose_name="出版社名字")# 数据信息    
INSERT INTO `test04_book` (`id`, `name`, `price`, `publish_name`) VALUES (1, '三国演绎', 99.00, '东方出版社');
INSERT INTO `test04_book` (`id`, `name`, `price`, `publish_name`) VALUES (2, '新三国', 105.00, '东方出版社');
INSERT INTO `test04_book` (`id`, `name`, `price`, `publish_name`) VALUES (3, '小王子', 89.00, '西方出版社');
INSERT INTO `test04_book` (`id`, `name`, `price`, `publish_name`) VALUES (4, '新能源', 99.00, '南方出版社');
INSERT INTO `test04_book` (`id`, `name`, `price`, `publish_name`) VALUES (5, '永动机', 105.00, '东方出版社');
INSERT INTO `test04_book` (`id`, `name`, `price`, `publish_name`) VALUES (6, '黑火药', 99.00, '北方出版社');
INSERT INTO `test04_book` (`id`, `name`, `price`, `publish_name`) VALUES (7, '支付宝', 109.00, '东方出版社');
INSERT INTO `test04_book` (`id`, `name`, `price`, `publish_name`) VALUES (8, '云电脑', 101.00, '西方出版社');
  • 序列化类
from rest_framework.serializers import ModelSerializer
from .models import Bookclass BookModelSerializer(ModelSerializer):class Meta:model = Bookfields = '__all__'
  • 视图函数和路由
# 视图层
from rest_framework.viewsets import ReadOnlyModelViewSet
from .serializer import BookModelSerializer
from .models import Bookclass BookAPIView(ReadOnlyModelViewSet):queryset = Book.objects.all()serializer_class = BookModelSerializer# 路由层
from django.urls import path, include
from .views import BookAPIView
from rest_framework.routers import SimpleRouterrouter = SimpleRouter()
router.register(prefix='books', viewset=BookAPIView, basename='books')
urlpatterns = [path('', include(router.urls))
]

【1】排序

(1)介绍

  • restful规范中,有提到查询地址中可以带条件,默认排序条件是pk
  • 即:
    • http://127.0.0.1:8000/test04/books/?ordering=price表示按照价格从低到高排序
    • http://127.0.0.1:8000/test04/books/?ordering=-price表示按照价格从高到低排序
    • http://127.0.0.1:8000/test04/books/?ordering=price,name表示价格从低到高,同价格的情况下,在名字以低到高排序

(2)简单使用

  • 必须要是继承 GenericAPIView 的视图类
  • filter_backends=[排序类, ]:排序类的地址
  • ordering_fields = ['子段1', '子段2'...]:这里的字段没有先后顺序,只是指定排序的字段可以有哪些
from rest_framework.filters import OrderingFilter, SearchFilterclass BookAPIView(ReadOnlyModelViewSet):queryset = Book.objects.all()serializer_class = BookModelSerializerfilter_backends = [OrderingFilter]ordering_fields = ['price', 'name']

image-20240417211107216

  • 注意:如果有自定义的内容,需要重写父类的方法比如List,一定要使用self.filter_queryset(self.get_queryset()),而不是使用self.get_queryset(),因为后者将没有排序的功能

【2】过滤

  • 如果提示UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list:
    • 可以在queryset后面加上.order_by('id')默认以id排序

(1)内置:多字段(与的条件)模糊匹配

  • 必须要是继承 GenericAPIView 的视图类

  • 和排序一样需要,需要添加两个类属性,不过有个是一样的,即过滤和排序是可以同时使用的

  • filter_backends=[过滤类, ]:过滤类的地址,这里的先后顺序不影响结果,只不过一个是先过滤再排序,一个是先排序再过滤

  • search_fields= ['子段1', '子段2'...]:这里的字段也没有先后顺序,只是指定排序的字段可以有哪些

  • 路由示例:http://127.0.0.1:8000/test04/books/?search=东

    • 根据search_fields的字段,模糊匹配含有东的
from rest_framework.filters import OrderingFilter, SearchFilterclass BookAPIView(ReadOnlyModelViewSet):queryset = Book.objects.all()serializer_class = BookModelSerializerfilter_backends = [OrderingFilter, SearchFilter]ordering_fields = ['price', 'name']search_fields = ['name', 'publish_name']

image-20240417213456133

(2)第三方过滤

  • 导包:

    • pip install django-filter
    • from django_filters.rest_framework import DjangoFilterBackend
  • 类属性:

    • filter_backends=[过滤类, ]:过滤类的地址,这里的先后顺序不影响结果,只不过一个是先过滤再排序,一个是先排序再过滤
    • filterset_fields= ['子段1', '子段2'...]:这里的字段也没有先后顺序,只是指定排序的字段可以有哪些
from django_filters.rest_framework import DjangoFilterBackendclass BookAPIView(ReadOnlyModelViewSet):queryset = Book.objects.all()serializer_class = BookModelSerializerfilter_backends = [DjangoFilterBackend]filterset_fields = ['price', 'publish_name']

image-20240417214858539

(3)自定义过滤类

  • 自定义的难度虽然大,但是这确实使用最多的

    • 需要写的类继承BaseFilterBackend
    • 重写filter_queryset方法
    • 并返回过滤以后的queryset对象
  • 示例要求:

    • 这里以价格或者书名进行过滤,可以两个同时给,可以不给,可以指定一个
    • 书名模糊匹配,价格是指定价格
from rest_framework.filters import BaseFilterBackend
from django.db.models import Qclass CommonFilter(BaseFilterBackend):def filter_queryset(self, request, queryset, view):name = request.query_params.get('name')price = request.query_params.get('price')# 两个参数都有if all([name, price]):queryset = queryset.filter(Q(name__contains=name) | Q(price=price))return queryset# 只用价格elif price:queryset = queryset.filter(price=price)return queryset# 只用书名elif name:queryset = queryset.filter(name__contains=name)return queryset# 视图层
from .filter import CommonFilter
class BookAPIView(ReadOnlyModelViewSet):queryset = Book.objects.all()serializer_class = BookModelSerializerfilter_backends = [CommonFilter]

image-20240417221224582

  • 示例二:只按照价格过滤,但是价格是一个区间
class CommonFilter(BaseFilterBackend):def filter_queryset(self, request, queryset, view):price_g = request.query_params.get('price1')price_l = request.query_params.get('price2')# 两个参数都有才过滤if all([price_g, price_l]):queryset = queryset.filter(Q(price__gte=price_g) & Q(price__lte=price_l))return queryset# 参数不全直接返回return queryset

image-20240417222116588

【3】分页

  • pagination_class不是一个列表,所以只能

(1)基本分页

  • 继承PageNumberPagination指定类变量
    • page_size = 2 默认每页数量,可以指定size超过数量
    • page_query_param = 'page' 路由页码关键字
    • page_size_query_param = 'size' 路由每页数量关键字
    • max_page_size = 10 每页最多显示数量
from rest_framework.pagination import PageNumberPaginationclass CommonPagination(PageNumberPagination):page_size = 2  # 默认每页数量page_query_param = 'page'  # 路由页码关键字page_size_query_param = 'size'  # 路由每页数量关键字max_page_size = 10  # 每页显示的最大条数# 视图函数
from .pagination import CommonPaginationclass BookAPIView(ReadOnlyModelViewSet):queryset = Book.objects.all()serializer_class = BookModelSerializerpagination_class = CommonPagination

image-20240417224703000

(2)偏移分页

  • 继承LimitOffsetPagination指定类变量
    • default_limit= 2 默认每页数量,可以指定limit超过数量
    • limit_query_param = 'limit' 路由每页数量关键字
    • offset_query_param= 'offset' 路由偏移量关键字
    • max_limit = 10 每页最多显示数量
from rest_framework.pagination import LimitOffsetPaginationclass CommonPagination(LimitOffsetPagination):default_limit = 2  # 默认每页数量limit_query_param = 'limit'  # 路由每页数量关键字offset_query_param = 'offset'  # 路由偏移量关键字max_limit = 10  # 每页最多显示数量

image-20240417230611468

(3)游标分页

  • 优势
    • 性能优化:游标分页不需要跳过任何行,它只需要从上一页的最后一个项目开始。这意味着数据库只需要处理实际需要的数据,而不是像偏移分页那样需要处理OFFSET指定的所有数据。这种特性使得游标分页在处理大量数据时具有更高的效率。
    • 数据一致性:即使有新的数据插入,也不会影响已经浏览过的页面。这是因为每一页的数据都是基于上一页的最后一个项目,而不是基于页数。这种特性确保了用户浏览的数据始终是最新的,避免了数据不一致的问题。
    • 用户体验:游标分页允许用户连续浏览数据,提供了更好的用户体验。这是因为游标分页是根据当前查询结果的位置来动态生成分页结果,使得用户可以无缝地浏览数据库中大量的数据。
  • 继承PageNumberPagination指定类变量
    • page_size= 2 默认每页数量,可以指定size超过数量
    • cursor_query_param = 'cursor' 路由关键字
    • ordering= 10 排序字段,必须有
      • ordering= ‘-created’:created有这个字段的,按照倒叙来
from rest_framework.pagination import CursorPagination
class CommonPagination(CursorPagination):cursor_query_param = 'cursor'  # 路由关键字page_size = 2  # 默认每页的数量ordering = 'id'  # 排序规则

image-20240417231334246

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博睿数据亮相GOPS全球运维大会,Bonree ONE 2024春季正式版发布!

2024年4月25日,博睿数据 Bonree ONE 2024 春季正式版焕新发布。同时,博睿数据AIOps首席专家兼产品总监贺安辉携核心产品新一代一体化智能可观测平台 Bonree ONE 亮相第二十二届 GOPS 全球运维大会深圳站。 Bonree ONE 2024 春季版产品重点升级数据采集、…

Linux实现Nginx的安装与部署并实现html静态资源访问

文章目录 一、安装过程二、常用命令三、查看状态并启动nginx四、放置静态资源五、访问 一、安装过程 1、安装依赖包 yum -y install gcc pcre-devel zlib-devel openssl openssl-devel 2、下载Nginx安装包wget https://nginx.org/download/nginx-1.16.1.tar.gz 3、解压 tar -z…

【学习笔记】Python 使用 matplotlib 画图

文章目录 安装中文显示折线图、点线图柱状图、堆积柱状图坐标轴断点参考资料 本文将介绍如何使用 Python 的 matplotlib 库画图,记录一些常用的画图 demo 代码 安装 # 建议先切换到虚拟环境中 pip install matplotlib中文显示 新版的 matplotlib 已经支持字体回退…

el-date-picker 禁用时分秒选择(包括禁用下拉框展示)

2024.04.26今天我学习了对el-date-picker进行禁用时分秒, 在使用el-date-picker组件的时候,我们有可能遇到需要把时分秒的时间固定,然后并且不能让他修改: 1714120999296 比如右上角的这个时间,我们要给它固定是‘08:…

“AI 程序员入职系列”第二弹:如何利用通义灵码光速改写项目编程语言?

通义灵码入职阿里云云原生团队后,已经展示过 Ta 生成单元测试和自动生成代码的强大实力。今天,阿里云后端工程师云徊将从项目开发的实际需求出发,演示通义灵码在开发工作中可提供的帮助。 通义灵码在 Git 开发项目中起到了哪些作用&#xff…

前端JS必用工具【js-tool-big-box】,防抖和节流的方法调用学习

这一小节,我们针对前端工具包(npm)js-tool-big-box的使用做一些讲解,主要是防抖和节流方面的。 目录 前言 1 安装和引入 2 防抖的调用学习 3 节流的调用学习 4 使用方法总结 前言 在前端项目中,经常涉及到防抖…

Rancher 应用商店离线环境使用

前言 Rancher (v2.5 ) 应用商店可以方便的安装 Helm3 构建的应用,并且支持私有 helm 应用仓库,方便了内网离线环境下的使用。本文以内网离线环境为前提、以 MySQL 5.7.43 版本为应用举例,从零开始手把手教你如何制作并应用。 1、环境准备 1.…

分布式密钥生成

可验证且无经销商 分布式密钥生成 (DKG) 是一种加密协议,使多方能够协作生成共享密钥,而无需任何一方完全了解密钥。 它通过在多个参与者之间分配信任来增强各种应用程序的安全性,从而降低密钥泄露的风险。 我们引入了一种可验证且无经销商的…

Python实现飞机大战

提供学习或者毕业设计使用,功能基本都有,不能和市场上正式游戏相提比论,请理性对待! 本博文将开启免费试读,如有您需要完整源码或者素材材料等,请订阅本专栏或者找博主购买!购买后将提供源码文件…

什么是独立服务器?独立服务器最全面介绍

独立服务器是单个客户端具有独占访问权的服务器类型,在服务器开发过程中,以前使用虚拟主机和虚拟独立服务器(VPS)的公司几乎不可避免地转向独立服务器。 什么是独立服务器? 独立服务器是单个客户端具有独占访问权的服…

Golang | Leetcode Golang题解之第50题Pow(x,n)

题目: 题解: func myPow(x float64, n int) float64 {if n > 0 {return quickMul(x, n)}return 1.0 / quickMul(x, -n) }func quickMul(x float64, n int) float64 {if n 0 {return 1}y : quickMul(x, n/2)if n%2 0 {return y * y}return y * y * …

随笔Ubuntu上的的一些使用

Ubuntu简易使用 常用指令 cdlsmkdirrf -rm 路径 换源 备份镜像 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak编辑文件设置 sudo gedit /etc/apt/sources.list清华源 # 阿里源 deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe mul…