首页 > 其他分享 >06-排序 分页 过滤

06-排序 分页 过滤

时间:2024-04-17 23:12:51浏览次数:28  
标签:06 0.1 price queryset publish filter 过滤 排序 class

排序

查询多条和全部才会用到排序

  • 排序关键字:ordering

查询字符串

查询字符串(Query String)是指在 URL 中以问号(?)开始的部分,用于向服务器传递参数。它由一个或多个键值对组成,每个键值对之间用 & 符号分隔。

例如,在以下 URL 中,查询字符串是 ?page=2&category=books

在django种如何使用排序 ?ordering=price

-- 按价格升序
http://127.0.0.1:8000/books/?ordering=price  
select * from dd_book_spider dbs order by price asc;

-- 按价格降序 字段面前写一个-号
http://127.0.0.1:8000/books/?ordering=-price
select * from dd_book_spider dbs order by price desc;

-- 多个排序,用英文逗号隔开即可,一样支持 - 号从大到小排序
http://127.0.0.1:8000/books/?ordering=publish,-price

-- 出版社降序,价格也降序
http://127.0.0.1:8000/v1/publish/?ordering=-publish,-price

如何使用 必须是继承 GenericAPIView 的视图类才能使用

# 导入模块
from rest_framework.filters import OrderingFilter

class PublishView(GenericViewSet, ListModelMixin):
    # 固定写法
    filter_backends = [OrderingFilter]
    # 按哪一个字段取过滤,记不住取源码查看
    ordering_fields = ['price', "name", "publish"]
    
   

# 源码 serializer_class
def get_default_valid_fields(self, queryset, view, context={}):
	# ...
    serializer_class = getattr(view, 'serializer_class', None)

定制指定格式

如果纯自己写,不生效。

如果按照下面的格式,生效。

只要调用了self.get_queryset() 就会实现过滤

class PublishView(GenericViewSet, ListModelMixin):
	# ...
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset()) # 主要是这句话
        serializer = BookSerializer(instance=queryset, many=True)
        return Response({"code": 100, "msg": "成功", "results": serializer.data})

过滤

drf的过滤 (模糊匹配)

按照指定的条件取过滤

如何使用 ?searsh=publish

# 导入模块
from rest_framework.filters import SearchFilter

class PublishView(GenericViewSet, ListModelMixin):
    # 固定写法
    filter_backends = [SearchFilter]
    # 按哪一个字段取过滤,记不住取源码查看
    search_fields = ['price', "name", "publish"]

过滤和排序支持一起使用 ?serach=publish&ordering=price

from rest_framework.filters import OrderingFilter, SearchFilter


filter_backends = [SearchFilter, OrderingFilter]
search_fields = ["name"]
ordering_fields = ["price"]


# 按纪念排序
http://127.0.0.1:8000/v1/publish/?search=纪念
        
# 按纪念排序然后按价格降序
http://127.0.0.1:8000/v1/publish/?search=纪念&ordering=-price  
        
        
# ================= 控制字段进行模糊匹配
ordering_fields = ["publish", "name"]

# 只要书名或者出版社带 北 都能匹配
http://127.0.0.1:8000/v1/publish/?search=北 

第三方的过滤(支持精准匹配)django-filter

如何使用 直接使用查询字符串

# 安装模块
pip install django-filter

# 导入模块
from django_filters.rest_framework import DjangoFilterBackend

# 使用(一样需要继承GenericAPIView视图类 )
class PublishView(GenericViewSet, ListModelMixin):    
    queryset = DdBookSpider.objects.all()
    serializer_class = BookSpiderSerializer
    
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ["price", "publish", "name"]
# 查询出版社为 九州出版社 并且价格为36的结果
http://127.0.0.1:8000/v1/publish/?publish=九州出版社&price=36

更多django-filter的用法:https://www.cnblogs.com/juelian/p/17560269.html

自定义过滤器(实现更高级的功能)

下面的这个写法就是

from rest_framework.filters import BaseFilterBackend
from django.db.models import Q


class CommonFilter(BaseFilterBackend):
    """
    request:表示客户端发送的 HTTP 请求,从而根据请求进行过滤操作。
    queryset:表示要进行过滤的查询集,通常是从数据库中获取的数据集合。
    view:  表示处理请求的视图类实例,即使用了自定义过滤器的视图类。
            通过 view 参数,可以访问视图类中定义的属性、方法等信息,以便根据视图的特定需求进行过滤操作。
    """
    def filter_queryset(self, request, queryset, view):
        name = request.query_params.get("name", None)
        price = request.query_params.get("price", None)   # --> 等同于 request.get("price")
        publish = request.query_params.get("publish", None)

        # queryset --> 视图层的 我这里是DdBookSpider.objects.all()
        # queryset 是可以一直 ... 查询的
        if name and price and publish:
            queryset = queryset.filter(Q(price=price) | Q(publish__contains=publish))
        
        if name:
            queryset = queryset.filter(name__contains=name)
        
        if price:
            queryset = queryset.filter(price=price)
            
        if publish:
            queryset = queryset.filter(publish__contains=publish)
            
        return queryset
    
# 视图层
from .filter import CommonFilter 

class PublishView(GenericViewSet, ListModelMixin):
    queryset = DdBookSpider.objects.all()
    serializer_class = BookSpiderSerializer
	
    # 写这个就可以了,不用写字段了
    filter_backends = [CommonFilter]

过滤和排序总结

  1. 必须继承 GenericAPIView
  2. 不论是自己写的过滤器,还是第三方的过滤器,都写在 filter_backends列表即可,会从左往右依次筛选
  3. 一般是过滤器+排序组合,而不是多个过滤器组合,因为每一个匹配规则都是不一样的
  4. 自定义的过滤器只需要写filter_backends就可以了,逻辑是我们后端自己取控制的

分页 (不建议重写list)

如果数据库的数据量很大,如果一次性把数据返回给前端肯定体验不好,也很消耗内存占用,这时候就使用到了分页。

  1. 使用了这个分页后,就可以放弃django默认的分页器了。
  2. 分页和过滤 排序 不冲突

分页的展现形式:

  1. web端:有页数
  2. 小程序等:上滑页面
from rest_framework.pagination import CursorPagination, PageNumberPagination, LimitOffsetPagination

方式1 基本分页 PageNumberPagination (推荐)

# 导入模块
from rest_framework.pagination import PageNumberPagination


# 写一个类 继承它
class CommonPagination(PageNumberPagination):
    # 定制几个类属性就可以了
    
    # n 每一页显示多少条,这里是10条 
    page_size = 10 
    
    
    # ?后面的查询参数 可以修改 前端指定数量会然后跳转到指定的页数
    # http://127.0.0.1:8000/v1/publish/?page=10
    page_query_param = 'page'

    # 每页最多显示几条
    # 比如下面 查询第10页每一页显示5条
    # http://127.0.0.1:8000/v1/publish/?page=10&size=5
    page_size_query_param = "size"
    
    
    # 控制size参数的最多条数 超过也是按照这个为准 比如定成了10 size为100 那么还是按10来
    max_page_size = 10


    # http://127.0.0.1:8000/v1/publish/?page=2&size=5  查询第2页 每页显示5条
    # http://127.0.0.1:8000/v1/publish/?page=6&size=599  查询第6页 每页显示10条
# 视图层
from .pagination import CommonPagination

class PublishView(GenericViewSet, ListModelMixin):
    queryset = DdBookSpider.objects.all()
    serializer_class = BookSpiderSerializer
    pagination_class = CommonPagination

image-20240417220849542

方式2 LimitOffsetPagination

from rest_framework.pagination import LimitOffsetPagination

class CommonLimitOffsetPagination(LimitOffsetPagination):
    # 每页显示几条 
    default_limit = 5 
    
    # 控制每页显示多少条
    # http://127.0.0.1:8000/v1/publish/?limit=5
    limit_query_param = 'limit'

    # 偏移量
    # http://127.0.0.1:8000/v1/publish/?offset=3 从第三条开始 取5条 (default_limit)
    # http://127.0.0.1:8000/v1/publish/?offset=4&limit=3  从第4条开始取3条 写了limit受limit控制
    offset_query_param = 'offset'
    
    # 每页最大的条数 写500也是10条
    max_limit = 10
# 视图层
from .pagination import CommonLimitOffsetPagination

# 限制超级管理员才可以访问
class PublishView(GenericViewSet, ListModelMixin):
    queryset = DdBookSpider.objects.all()
    serializer_class = BookSpiderSerializer
    pagination_class = CommonLimitOffsetPagination

image-20240417221712570

方式3 CursorPagination

  1. 必须先排序
  2. 页数不确定以及很多使用
# 分页
from rest_framework.pagination import CursorPagination

# 必须先排序  只能上一页或者下一页 不能直接跳转到某一页
# 在app端上使用的比较多,效率最高,数据量越大越明显 比如几十万条
class CommonCursorPagination(CursorPagination):
    cursor_query_param = 'cursor' # 查询条件 同上面的 limit page
    page_size = 10 # 每一页显示的条数
    ordering = 'id' # 按照什么去排序

image-20240417223607757

标签:06,0.1,price,queryset,publish,filter,过滤,排序,class
From: https://www.cnblogs.com/ccsvip/p/18142026

相关文章

  • C++排序问题
    冒泡排序若得到一个从小到大的数组例如:3527481角标:1234567就是角标1和角标2比,若1大于2,就交换位置,然后角标2和角标3比,若2大于3,就交换位置第一趟:3254718第二趟:2345178以此类推。。。。点击查看代码#include<bits/stdc++.h>usingnamespaces......
  • drf之认证、权限、频率控制、排序、过滤、分页
    【认证】models.py1fromdjango.dbimportmodels234#Createyourmodelshere.5classUser(models.Model):6username=models.CharField(max_length=50)7password=models.CharField(max_length=50)8user_type=models.IntegerFiel......
  • 06_QT网络编程之UDP通信
    QT网络编程之UDP通信udp编程​ udp不分客户端和服务器,只需要使用一个类QUdpSocket。代码Udp.pro#-------------------------------------------------##ProjectcreatedbyQtCreator2024-04-13T23:07:41##-------------------------------------------------QT......
  • 构建之法06
    在阅读完第六章后,我深感敏捷开发的思想和实践方法对我的工作有很大的启发。在我的实际工作中,我也尝试了一些敏捷开发的做法。首先,我更加注重与团队成员的沟通和协作。我们定期召开面对面的会议,讨论项目的进展、遇到的问题以及下一步的计划。这种沟通方式不仅提高了我们的工作效率......
  • js带注释的冒泡排序算法
    一、简述冒泡排序(BubbleSort)是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果二者的顺序(如从大到小、首字母从A到Z)错误就交换。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。这个算法......
  • MyBatis-06-Spring的SqlSession和原始区别
    DefaultSqlSession这个就不说了,SQL执行是调用执行器Executor执行SqlSessionTemplate构造函数,虽然没有立即创建SqlSession传入代理拦截器SqlSessionInterceptor,但是拦截器是一个实例内部类,可以访问到SqlSessionFactory并且SqlSessionTemplate不支持commit、rollback......
  • 06 Vue3插槽
    6.9.【slot】1.默认插槽父组件中:<Categorytitle="今日热门游戏"><ul><liv-for="gingames":key="g.id">{{g.name}}</li></ul></Category>子组件中:......
  • 立创泰山派学习06--TF挂载及测试
    1、关机(poweroff)断电,再插入TF卡2、开机,查看内核日志dmesg|grepmmcdmesg-c(查看并清除内核日志)      或者fdisk-l    3、创建一个目录,用于挂载TF卡sudo mkdir/media/sdcard      或者直接挂载到/mnt/sdcar......
  • list集合的排序
    list集合的排序使用常用的sort方法排序和stream流的方式排序packagecom.liucy.meiriyilian.sort;importjava.util.ArrayList;importjava.util.Collections;importjava.util.Comparator;importjava.util.List;importjava.util.stream.Collectors;/***@Authorli......
  • 《线性代数的本质》(06-附注2-07)
    06-逆矩阵、列空间、秩与零空间线性方程组:A\(\vec{x}\)=\(\vec{v}\)线性代数的一个作用:帮助我们处理线性方程组。形式:矩阵与向量的乘法。几何意义:寻找一个向量\(\vec{x}\),这个向量在特定的线性变换之后与目标向量\(\vec{v}\)重合。行列式不等于0:有且仅有一个向量再变......