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

news2025/1/12 20:53:24

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

【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 models

class 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 Book

class BookModelSerializer(ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'
  • 视图函数和路由
# 视图层
from rest_framework.viewsets import ReadOnlyModelViewSet
from .serializer import BookModelSerializer
from .models import Book

class BookAPIView(ReadOnlyModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    
# 路由层
from django.urls import path, include
from .views import BookAPIView
from rest_framework.routers import SimpleRouter

router = 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, SearchFilter

class BookAPIView(ReadOnlyModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    filter_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, SearchFilter

class BookAPIView(ReadOnlyModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    filter_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 DjangoFilterBackend

class BookAPIView(ReadOnlyModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    filter_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 Q

class 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 = BookModelSerializer
    filter_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 PageNumberPagination


class CommonPagination(PageNumberPagination):
    page_size = 2  # 默认每页数量
    page_query_param = 'page'  # 路由页码关键字
    page_size_query_param = 'size'  # 路由每页数量关键字
    max_page_size = 10  # 每页显示的最大条数

# 视图函数
from .pagination import CommonPagination

class BookAPIView(ReadOnlyModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    pagination_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 LimitOffsetPagination


class 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.coloradmin.cn/o/1618456.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL8.0.36-社区版:二进制日志(4)

什么是二进制日志(binlog):记录了所有的ddl和dml语句,但是不包括查询类的 二进制日志的作用:1.灾难恢复,2.mysql主从复制 查看二进制日志状态 show variables like %log_bin%; 在mysql8中默认是开启的 | l…

TLV61048非同步升压BOOST转换器输入电压2.6-5.5V输出电流4A输出电压最高15V

推荐原因: 输入电压较低,输出电流可达3.5A SOT23-6封装 批量价格约0.70元 TLV61048引脚 TLV61048引脚功能 7 详细说明 7.1 概述 TLV61048是一款非同步升压转换器,支持高达 15 V 的输出电压和输入范围从 2.61 V 到 5.5 V。该TLV61048集成了…

C++ map和set的应用

1. 关联式容器 我们已经接触过STL中的部分容器,比如:vector、list、deque、 forward_list(C11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。那什么是关联式容器?它…

如何用Java语言实现远程控制多路照明

如何用Java语言实现远程控制多路照明呢? 本文描述了使用Java语言调用HTTP接口,实现控制多路照明。通过多路控制器,可独立远程控制多路照明。 可选用产品:可根据实际场景需求,选择对应的规格 序号设备名称1智能WiFi控…

hcia datacom课程学习(7):直连路由、静态路由

直连路由路由器接口上的网络(接口配置了IP地址并且开启)静态路由管理员手工添加的网络动态路由路由器之间动态学习形成的网络 1.直连路由 每当给路由器的一个接口配置了ip,路由表中就会产生对应的直连路由 配置路由接口ip的命令&#xff1…

编辑个人百度百科词条的小窍门,让你一次通过!

个人百度百科词条展示的是个人专业素养和成就,能够提升个人品牌形象,增加社交圈子中的竞争力。个人百度百科词条编辑攻略:如何通过审核?大家好!今天伯乐网络传媒来分享一个超实用的经验——如何编辑个人百度百科词条才…

VM安装openwrt

openwrt是什么 OPENWRT是一种嵌入式操作系统,旨在取代原始路由器 固件 ,并提供更多功能和自定义选项。 它构建在Linux内核之上,并由一系列 软件 包组成,以满足各种网络需求。 下载 官网下载地址:Index of /releases…

力扣-2259移除指定数字得到的最大结果

思路: 1. def removeDigit(self, number: str, digit: str) -> str::这是一个类方法,接受两个参数 number 和 digit,分别表示输入的数字字符串和要移除的数字字符,返回一个字符串。 2. n len(number)&#xff1a…

内网穿透工具(zerotier, tailscale)

内网穿透工具 zerotier tailscale 一、Zerotier1. Zerotier 网页注册2. Zerotier 网页使用(1) Zerotier 网页配置 3. Zeritier 终端配置(1) Zeritier 终端下载(2) Zeritier 终端连接 二、Tailscale1. 进入主页2. Tailscale 网页注册登录3. Tailscale 网页添加设备4. Tailscale …

解决方案 SHUTDOWN_STATE xmlrpclib.py line: 794 ERROR: supervisor shutting down

Supervisor操作命令 重新加载 Supervisor 配置: sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl restart all这将重新读取 Supervisor 的配置文件,更新进程组,然后重启所有进程。 查看 Supervisor 日志&#xff1…

【系统架构师】-选择题(一)

1、信息系统规划方法中,关键成功因素法通过对关键成功因素的识别,找出实现目标所需要的关键信息集合,从而确定系统开发的 (优先次序) 。关键成功因素来源于组织的目标,通过组织的目标分解和关键成功因素识别…

南京林业大学阮宏华团队揭示干旱对杨树人工林土壤微生物残留物碳的影响

全球强度干旱事件的频繁发生,对陆地生态系统土壤有机碳库可能产生显著影响。土壤微生物残体碳是土壤有机碳库的重要组成部分,微生物残体碳的变化对土壤有机碳库产生显著影响。然而,土壤中微生物残体碳对干旱的响应及其机制还不清楚。 基于此…

实现基于RAG的QA应用程序

实现基于RAG的Q&A应用程序 LLM 支持的最强大的应用程序之一是复杂的 问答 (Q&A) 聊天机器人。这些应用程序可以 回答有关特定来源信息的问题。这些应用程序 使用一种称为检索增强生成 (RAG) 的技术。 什么是检索增强生成…

TCP/IP常用协议栈图解

1.引言 最近看了一些计算机网络的课程,总结借鉴了一些TCP/IP常用协议,罗列在以下图中,以便有一个整体观。 2.图解 先上图 3.总结 TCP/IP协议是实际用的计算机网络通信的标准协议栈,自上而下分为应用层,传输层&#xf…

世界读书日 | 开发者必读书单重磅来袭,华为云DTSE专家天团力荐

春色恰如许,读书正当时。 读书,就像解锁一把神秘钥匙,为开发者洞开新世界的大门,赋予他们破译复杂难题的能力、挑战未知领域的勇气。书页翻动间,开发者得以站在巨人的肩膀上,汲取前人经验,积蓄…

BBS前后端混合项目--01

总路由 # urls.py """BBS1 URL ConfigurationThe urlpatterns list routes URLs to views. For more information please see:https://docs.djangoproject.com/en/3.2/topics/http/urls/ Examples: Function views1. Add an import: from my_app import views2…

AI测试干货!实例讲解AI自动生成测试用例

1.引言 在软件开发过程中,测试用例的生成是至关重要的一步。测试用例是用于验证软件功能、性能和安全性的具体测试方法,是确保软件质量的关键手段。 随着人工智能(AI)技术的发展,基于AI的测试用例生成技术逐渐成为未…

docker容器内彻底移除iptables服务的实现方法

背景 我创建的容器使用的是centos6的标准镜像,所以内置了iptables服务。容器启动后iptables服务默认就启动了。iptables设置的规则默认是所有流量都无法通行。而对于服务器的管理使用的是宿主机的防火墙。这样就导致在实现用iptables动态给容器添加端口映射时不成功…

Some App Tech Support

Getting Support:  mail: 842529824qq.com wx: g842529824  or leave comment below.

研究发现:90%的Java服务容易第三方漏洞的影响

Datadog最新发布的“2024年DevSecOps状况”报告显示,Java服务在受Datadog最新发布的“2024年DevSecOps状况”报告显示,Java服务在受到第三方漏洞影响方面最为严重。 报告指出,90%的Java服务存在一个或多个严重或高危漏洞,这些漏…