首页 > 其他分享 >DRF之过滤 排序 分页

DRF之过滤 排序 分页

时间:2024-04-25 22:22:27浏览次数:16  
标签:size price queryset 过滤 数据量 query 排序 page DRF

DRF之过滤 排序 分页

  • 使用【过滤 排序 分页】都需要在继承了GenericAPIView的视图类下使用
  • 并指定类属性【queryset 和 serializer_class】

【一】过滤

# 所有过滤类都继承 【BaseFilterBackend】
from rest_framework.filters import BaseFilterBackend

【1】drf自带的过滤

# 导入模块
from rest_framework.filters import SearchFilter
# SearchFilter : 模糊匹配
  • 常用的配置属性
    • search_param: 这个属性用于指定 URL 查询参数的名称,该参数将用于搜索。默认值通常为 "search"
    • search_title: 用于在浏览器可视化界面中定义搜索输入字段的标题。这主要用于 API 浏览器。
    • search_description: 类似于 search_title,此属性用于定义搜索字段的描述,这同样显示在 API 浏览器中。
    • search_fields: 这个属性是一个字符串列表,指定了哪些字段应当被包含在搜索中。
      • 字段可以指定一些前缀
        • ^: 这个前缀表示进行前缀匹配,即以指定值开头的匹配。在 Django ORM 中,对应的查询方法是 istartswith,表示大小写不敏感的前缀匹配。
        • =: 这个前缀表示进行精确匹配,即完全匹配指定值的项。在 Django ORM 中,对应的查询方法是 iexact,表示大小写不敏感的精确匹配。
        • @: 这个前缀表示进行全文搜索,即在文本字段中进行全文搜索匹配。在 Django ORM 中,对应的查询方法是 search,通常与数据库全文搜索功能配合使用。
        • $: 这个前缀表示使用正则表达式进行匹配。在 Django ORM 中,对应的查询方法是 iregex,表示大小写不敏感的正则表达式匹配。

【1.1】使用

  • 使用过滤和排序都需要在继承了GenericAPIView的视图类下使用
class BookView(ModelViewSet):
    # 需要定义queryset
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 将过滤类配置在列表中
    filter_backends = [SearchFilter]
    # 指定过滤字段
    search_fields = ['title', 'publish']
    
    # search_fields = ['^title', '=publish']
    ### ^ 表示搜索时对 title 字段进行前缀匹配
    ### = 表示对 publish 进行精确匹配

image-20240425211118908

【2】第三方模块Django-filter

django-filter 功能还挺强大的,此处只演示精准匹配,其他过滤请移步官方文档或搜索一下

常用自定义过滤器或drf自带的就够用了

# 精准匹配
from django_filters.rest_framework import DjangoFilterBackend

class CarModelView(ModelViewSet):
    queryset = CarModel.objects.all()
    serializer_class = CarModelSerializer
    # 第三方过滤模块,精准过滤
    filter_backends = [DjangoFilterBackend]
    # 以车型的名称过滤
    filterset_fields = ['name']

image-20240425213334161

image-20240425213345994

【3】自定义过滤

# 继承【BaseFilterBackend】
from rest_framework.filters import BaseFilterBackend
class 过滤类(BaseFilterBackend):
    # 重写 【filter_queryset】 方法
     def filter_queryset(self, request, queryset, view):
            '''
            :param request: request对象
            :param queryset: 待过滤的qs对象
            :param view: 视图类
            :return: 过滤后的qs
            '''
            return filtered_queryset

【3.1】实例

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


class CommonFilter(BaseFilterBackend):

    def filter_queryset(self, request, queryset, view):
        # 获取传入的参数
        query_params = request.query_params
        # 过滤书名
        title = query_params.get('title')
        # 比gt的值大
        price_gt = query_params.get('price_gt')
        # 比lt的值小
        price_lt = query_params.get('price_lt')
        if all([title, price_lt, price_gt]):
            queryset = queryset.filter(Q(title__contains=title) | Q(price__gt=price_gt, price__lt=price_lt))
        elif title:
            queryset = queryset.filter(title__contains=title)
        elif all([price_lt, price_gt]):
            queryset = queryset.filter(price__gt=price_gt, price__lt=price_lt)
        elif price_lt:
            queryset = queryset.filter(price__lt=price_lt)
        elif price_gt:
            queryset = queryset.filter(price__gt=price_gt)
        else:
            pass
        return queryset

【二】排序

# 排序使用drf自带的排序即可
from rest_framework.filters import OrderingFilter
# 也可以自定义  # 继承BaseFilterBackend  # 重写【filter_queryset】方法即可
from rest_framework.filters import BaseFilterBackend

【1】OrderingFilter

from rest_framework.filters import OrderingFilter
  • 常用的属性
    • ordering_param:
      • 这个属性用来定义用于排序的查询参数的名称。默认值是 "ordering"。当你想要通过 URL 参数来控制排序时,这是使用的参数名。
    • ordering_fields:
      • 这个属性定义了可以用于排序的字段列表。如果未指定此属性,则允许对所有模型字段进行排序。
      • 指定这个属性后,只有在这个列表中的字段才可以用来排序。
    • ordering_description:
      • 用于描述排序参数的用途,这主要用于 API 文档和浏览器界面中。

【1.1】使用

class BookView(GenericViewSet, RetrieveModelMixin, ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    # 排序
    filter_backends = [OrderingFilter]
    ordering_fields = ['price', 'publish']
  • 【注】只有在ordering_fields中的字段使用ordering=字段才生效

image-20240425214924487

【三】分页

# 分页drf自带了三种  # 基本上这三种也够用了
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination

【1】PageNumberPagination

from rest_framework.pagination import PageNumberPagination


class CommonPagePagination(PageNumberPagination):
    page_size = 2  # 每页展示2条数据
    page_query_param = 'page'  # 通过page参数指定页数
    page_size_query_param = 'size'  # 通过size指定展示条数
    max_page_size = 10  # 最大的size条数  # 用户如果输入超过也只展示10条

    last_page_strings = ('last',)  # 通过page=last 可以跳转到最后一页
    
    
    # 可以通过重写【get_paginated_response】方法定义返回格式
    def get_paginated_response(self, data):
        return Response({
            'code': 100,
            'msg': '查看成功',
            'count': self.page.paginator.count,
            'next': self.get_next_link(),
            'previous': self.get_previous_link(),
            'results': data,
        })
  • 常用属性
    • page_size:
      • 每页返回的数据数量,默认为 None,表示不进行分页,返回所有数据。
    • page_size_query_param:
      • 用于指定每页数据量的查询参数名称,默认为 "page_size"
      • 可以通过 URL 查询参数来指定每页返回的数据量。
    • max_page_size:
      • 每页数据量的最大值,默认为 None,表示不做限制。
      • 如果用户指定的每页数据量超过 max_page_size,则会返回 max_page_size 的数据量。
    • page_query_param:
      • 用于指定页码的查询参数名称,默认为 "page"
      • 可以通过 URL 查询参数来指定要获取的页码。
    • page_size_query_description:
      • 用于描述每页数据量查询参数的用途,通常在 API 文档和浏览器界面中使用。

下述图片与上述展示代码不一致,设置的size 为10

############ 下图的count指的是数据总数为10,不是展示的数量 ##############

image-20240425215724618

【2】LimitOffsetPagination

################### pagination.py ############
from rest_framework.pagination import LimitOffsetPagination


class CommonPagination(LimitOffsetPagination):
    default_limit = 5
    limit_query_param = 'limit'
    offset_query_param = 'offset'
    max_limit = 10
##################### views.py ########
class BookView(GenericViewSet, RetrieveModelMixin, ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
	
    # 【注】 分页只能使用一个,所以不需要使用列表
    pagination_class = CommonPagination
  • 常用属性
    • default_limit:
      • 默认的每页返回的数据数量,如果未指定,则默认为 None,表示不进行分页,返回所有数据。
    • limit_query_param:
      • 用于指定每页数据量的查询参数名称,默认为 "limit"
      • 可以通过 URL 查询参数来指定每页返回的数据量。
    • offset_query_param:
      • 用于指定偏移量的查询参数名称,默认为 "offset"
      • 可以通过 URL 查询参数来指定数据的偏移量。
    • max_limit:
      • 每页数据量的最大值,默认为 None,表示不做限制。
      • 如果用户指定的每页数据量超过 max_limit,则会返回 max_limit 的数据量。
    • limit_query_description:
      • 用于描述每页数据量查询参数的用途,通常在 API 文档和浏览器界面中使用。
    • offset_query_description:
      • 用于描述偏移量查询参数的用途,通常在 API 文档和浏览器界面中使用。

image-20240425220324347

【3】CursorPagination

################### pagination.py ############
from rest_framework.pagination import CursorPagination


class CommonCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'
    page_size = 5
    ordering = 'id'  # 该排序字段必须是数据中包含的
    max_page_size = 20
##################### views.py ########
class BookView(GenericViewSet, RetrieveModelMixin, ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
	
    # 【注】 分页只能使用一个,所以不需要使用列表
    pagination_class = CommonCursorPagination

image-20240425221129011

  • 常用属性
    • ordering:
      • 用于指定用于排序的字段或字段列表。必须是模型中存在的字段。
      • 排序字段用于确保结果集的一致性,并允许游标分页正常工作。
    • cursor_query_param:
      • 用于指定游标查询参数名称,默认为 "cursor"
      • 客户端通过这个查询参数传递游标值。
    • page_size:
      • 每页返回的数据数量,默认为 None,表示不进行分页,返回所有数据。
    • max_page_size:
      • 每页数据量的最大值,默认为 None,表示不做限制。
      • 如果用户指定的每页数据量超过 max_page_size,则会返回 max_page_size 的数据量。
    • cursor_page_query_param:
      • 用于指定游标分页查询参数名称,默认为 "page"
      • 客户端通过这个查询参数指定要获取的页码。
    • cursor_page_size:
      • 每次查询返回的最大结果集大小,默认为 None,表示不做限制。
      • 如果结果集大小超过 cursor_page_size,则可能会被截断。

【4】三种分页方式的区别

这三种分页方式在实现上有一些区别,主要体现在以下几个方面:

  1. 分页原理
    • PageNumberPagination:基于页码的分页方式,客户端通过指定页码来请求相应页的数据。
    • LimitOffsetPagination:基于偏移量和限制数量的分页方式,客户端通过指定偏移量和每页数据数量来请求数据。
    • CursorPagination:基于游标的分页方式,客户端通过游标来请求数据,游标指向结果集中的某个特定位置。
  2. 适用场景
    • PageNumberPagination:适用于数据量相对较小且页码比较直观的场景,例如博客文章列表等。
    • LimitOffsetPagination:适用于需要精确控制数据范围的场景,但可能存在性能问题,特别是在数据量较大时。
    • CursorPagination:适用于数据量较大、需要快速高效获取数据、或者需要实现无限滚动等需求的场景,因为它不需要在每次请求时计算偏移量,性能更好。
  3. 性能影响
    • PageNumberPaginationLimitOffsetPagination 都需要在每次请求时计算偏移量,因此在处理大数据量时可能存在性能问题,特别是在接近数据末尾时。
    • CursorPagination 通过游标来定位数据,避免了每次请求都重新计算偏移量,因此在处理大数据量时性能更好,尤其是在数据集增长时。

标签:size,price,queryset,过滤,数据量,query,排序,page,DRF
From: https://www.cnblogs.com/Lea4ning/p/18158746

相关文章

  • 笔记:拓扑排序
    定义拓扑排序(Topologicalsorting),是对一个DAG排序的算法。对于排序后的序列\(s\),设\(t_i\)是节点\(i\)在\(s\)中的位置,那么该DAG上的每条边\(u\tov\),\(t_u<t_v\)。换句话说,就是每条边\(u\tov\),\(u\)不能在\(v\)的后面。模板link。考虑两种算法,分别基于广......
  • 02-属性事件过滤双向绑定
    es6的对象写法//正常的写法letarr=['逃课','打游戏','欺负小满']lethobbyDetail={name:"大乔",age:4,hobby:arr}console.log(hobbyDetail)//简写//正常的写法letarr=['逃课','打游戏','欺负小满'......
  • vue中函数使用、class和style属性、条件渲染、列表渲染、数据的双向绑定、input事件、
    【事件指令中的函数使用】1<!DOCTYPEhtml>2<htmllang="en">3<head>4<metacharset="UTF-8">5<title>Title</title>6<scriptsrc="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&......
  • DRF之三大认证【认证 权限 频率】
    DRF之三大认证【一】三大认证执行顺序【二】认证#我们如果想要自定义认证类,都需要继承【BaseAuthentication】fromrest_framework.authenticationimportBaseAuthentication【1】源码【2】认证类的使用###############################authentications.py#####......
  • Elasticsearch - filter过滤器
    通过query查询eg:查询desc中有"Facebook官网"并且价格在7-20之间的数据在只查询desc中有"Facebook官网"时,返回的_score分别是3.598,0.097GET/book/_search{"query":{"bool":{"must":[{"match":{......
  • DRF之路由组件
    五】路由组件资源路由允许你快速声明给定的有足够控制器的所有公共路由。而不是为你的index...声明单独的路由,一个强大的路由能在一行代码中声明它们。—RubyonRails文档【1】使用SimpleRouter快速生成路由from.viewsimportTaskViewV3#导入模块fromrest_framewor......
  • 二分法,冒泡排序
    Ⅰ算法之二分法算法其实就是解决问题的有效方法'''二分法使用有前提:数据集必须有先后顺序(升序,降序)''''''二分法原理 获取数据集中间的元素比对大小 如果中间元素大于目标数据那么保留数据集的左边一半 如果中间元素小于目标数据那么保留数据集的右边一半 针对剩......
  • blog.admin 查询增加过滤器,添加、删除增加数据审计、统一控制权限操作
    一、查询增加过滤器需求说明:有几张表(医生表、病人表等),有个字段ClinicID都与诊所表主键Id关联。用户登录系统时候,根据所分配的诊所权限,只查看自己诊所的数据。通过查询过滤器,在查询每个表的时候,自动将ClinicID==当前登录用户所属ClinicID,添加上。1、创一个IClinicEntity接口usi......
  • 冒泡排序
    packageArray;importjava.util.Arrays;//冒泡排序//1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置//2.每一次比较,都会产生一个最大,或者最小的数字//3.下一轮测试可以少一次排序//4.依次循环,直到结束publicclassDemo06{publicstaticvoid......
  • 笔记/C++中的数组排序
    在C++中,std::sort函数是一个用于对容器(如数组、向量等)进行排序的通用算法。它定义在<algorithm>头文件中,并接受两个迭代器参数,分别指向要排序的范围的开始和结束位置。此外,std::sort还可以接受一个可选的比较函数或lambda表达式,用于自定义排序规则。以下是std::sort函数的基本用......