DRF之过滤 排序 分页
- 使用【过滤 排序 分页】都需要在继承了
GenericAPIView
的视图类下使用
- 并指定类属性【queryset 和 serializer_class】
【一】过滤
| |
| from rest_framework.filters import BaseFilterBackend |
【1】drf自带的过滤
| |
| from rest_framework.filters import 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 = Book.objects.all() |
| serializer_class = BookSerializer |
| |
| filter_backends = [SearchFilter] |
| |
| search_fields = ['title', 'publish'] |
| |
| |
| |
| |

【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'] |


【3】自定义过滤
| |
| from rest_framework.filters import BaseFilterBackend |
| class 过滤类(BaseFilterBackend): |
| |
| 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') |
| |
| price_gt = query_params.get('price_gt') |
| |
| 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 |
【二】排序
| |
| from rest_framework.filters import OrderingFilter |
| |
| 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=字段
才生效

【三】分页
| |
| from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination |
| from rest_framework.pagination import PageNumberPagination |
| |
| |
| class CommonPagePagination(PageNumberPagination): |
| page_size = 2 |
| page_query_param = 'page' |
| page_size_query_param = 'size' |
| max_page_size = 10 |
| |
| last_page_strings = ('last',) |
| |
| |
| |
| 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,不是展示的数量 ##############

| |
| from rest_framework.pagination import LimitOffsetPagination |
| |
| |
| class CommonPagination(LimitOffsetPagination): |
| default_limit = 5 |
| limit_query_param = 'limit' |
| offset_query_param = 'offset' |
| max_limit = 10 |
| |
| 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 文档和浏览器界面中使用。

| |
| from rest_framework.pagination import CursorPagination |
| |
| |
| class CommonCursorPagination(CursorPagination): |
| cursor_query_param = 'cursor' |
| page_size = 5 |
| ordering = 'id' |
| max_page_size = 20 |
| |
| class BookView(GenericViewSet, RetrieveModelMixin, ListModelMixin): |
| queryset = Book.objects.all() |
| serializer_class = BookSerializer |
| |
| |
| pagination_class = CommonCursorPagination |

- 常用属性
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】三种分页方式的区别
这三种分页方式在实现上有一些区别,主要体现在以下几个方面:
- 分页原理:
- PageNumberPagination:基于页码的分页方式,客户端通过指定页码来请求相应页的数据。
- LimitOffsetPagination:基于偏移量和限制数量的分页方式,客户端通过指定偏移量和每页数据数量来请求数据。
- CursorPagination:基于游标的分页方式,客户端通过游标来请求数据,游标指向结果集中的某个特定位置。
- 适用场景:
- PageNumberPagination:适用于数据量相对较小且页码比较直观的场景,例如博客文章列表等。
- LimitOffsetPagination:适用于需要精确控制数据范围的场景,但可能存在性能问题,特别是在数据量较大时。
- CursorPagination:适用于数据量较大、需要快速高效获取数据、或者需要实现无限滚动等需求的场景,因为它不需要在每次请求时计算偏移量,性能更好。
- 性能影响:
- PageNumberPagination 和 LimitOffsetPagination 都需要在每次请求时计算偏移量,因此在处理大数据量时可能存在性能问题,特别是在接近数据末尾时。
- CursorPagination 通过游标来定位数据,避免了每次请求都重新计算偏移量,因此在处理大数据量时性能更好,尤其是在数据集增长时。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了