drf : 过滤 排序 分页

过滤和排序

并不是所有的接口都需要写,查询所有才需要过滤(根据条件过滤),排序(按某个规则排序,也可倒序)。

导入模块:
"""
OrderingFilter : 排序
SearchFilter : 过滤
"""
from rest_framework.filters import OrderingFilter,SearchFilter

过滤,内置的过滤,必须继承GenericAPIView,才会有这个类属性。

作用:模糊匹配原则,查询关键字只能为search

views.py
from rest_framework.filters import SearchFilter
class BookAPIView(ViewSetMixin,ListAPIView):
queryset = Books.objects.all()
serializer_class = BookSerializers
# 在视图类中配置,最顶层至少是GenericAPIView,GenericAPIView中有filter_backends
filter_backends = [SearchFilter,]
# 过滤条件:按自钉子字段过滤
search_fields = ['price']

排序

view.py

from rest_framework.filters import OrderingFilter
class BookAPIView(ViewSetMixin,ListAPIView):
queryset = Books.objects.all()
serializer_class = BookSerializers
# 在视图类中配置,最顶层至少是GenericAPIView,GenericAPIView中有filter_backends
filter_backends = [OrderingFilter]
# 按照那个字段排序
ordering_fields = ['id']

过滤和排序组合

views.py

"""
OrderingFilter : 排序
SearchFilter : 过滤
"""
from rest_framework.filters import OrderingFilter,SearchFilter
class BookAPIView(ViewSetMixin,ListAPIView):
queryset = Books.objects.all()
serializer_class = BookSerializers
# 在视图类中配置,最顶层至少是GenericAPIView,GenericAPIView中有filter_backends
filter_backends = [SearchFilter,OrderingFilter]
# 过滤条件:按名字过滤
search_fields = ['name']
# 按照那个字段排序
ordering_fields = ['id']
# 排序可以多个条件排序,前提第一个条件要一直
ordering_fields = ['id','price']


按照name字段(西)过滤,按到id字段倒序过滤,正序不用加-。

如果多个条件排序: http://127.0.0.1:8000/books/?ordering=-id,100

第三方过滤

作用:只能精准匹配,查询字为字段名。

安装:
pip install django-filter

导入模块:

from django_filters.rest_framework import DjangoFilterBackend

注册:

INSTALLED_APPS = [
'django_filters'
]

views.py,视图层

from django_filters.rest_framework import DjangoFilterBackend
class BookAPIView(ViewSetMixin, ListAPIView):
queryset = Books.objects.all()
serializer_class = BookSerializers
filter_backends = [DjangoFilterBackend, ]
# 过滤条件:按名字过滤
filterset_fields = ['name']
# 按照那个字段排序
ordering_fields = ['id']

第三方过滤查询多个

自定义过滤器

作用:模糊匹配与精准匹配,查询关键字为字段名。

开设一个filter.py文件。

from rest_framework.filters import BaseFilterBackend
class MyFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
# <rest_framework.request.Request: GET '/books/?name=%E8%A5%BF'>
print(request)
"""
过滤前的数据
<QuerySet
[<Books: Books object (1)>,
<Books: Books object (2)>,
<Books: Books object (3)>,
<Books: Books object (4)>,
<Books: Books object (5)>]>
"""
print(queryset)
query = request.query_params.get('name')
if query:
# 西
print(query)
queryset = queryset.filter(name__contains=query)
"""
过滤后的数据。
<QuerySet
[<Books: Books object (1)>,
<Books: Books object (2)>,
<Books: Books object (3)>]>
"""
print(queryset)
return queryset

views.py

from .filter import MyFilter

自定义过滤

class BookAPIView(ViewSetMixin, ListAPIView):
queryset = Books.objects.all()
serializer_class = BookSerializers
filter_backends = [MyFilter, ]


分页

首先:在五个接口中,只有查询所有才涉及到分页。

默认提供三种分页方式:

  • PageNumberPagination
  • LimitOffsetPagination
  • CursorPagination
    导入模块
from rest_framework.pagination import PageNumberPagination,CursorPagination,LimitOffsetPagination

基本分页,使用频率高:PageNumberPagination

导入模块:

from rest_framework.pagination import PageNumberPagination

需要重写PageNumberPagination中的四个类方法。

page.py

from rest_framework.pagination import PageNumberPagination, CursorPagination, LimitOffsetPagination
class MyPageNumberPagination(PageNumberPagination):
# 每页显示条数
page_size = 3
# 查询条件为page --> ?page=页数
page_query_param = 'page'
# 每页显示的条数的查询条件,?page=3&size=9 查询第三页,第三页显示9条
page_size_query_param = 'size'
# 控制每页上限数据为几条
max_page_size = 5

views.py

from rest_framework.generics import ListAPIView
from rest_framework.viewsets import ViewSetMixin
from .filter import MyFilter
from .page import MyPageNumberPagination
# 自定义过滤
class BookAPIView(ViewSetMixin, ListAPIView):
queryset = Books.objects.all()
serializer_class = BookSerializers
filter_backends = [MyFilter, ]
# 分页只要一种方式,必须继承GenericAPIView类
pagination_class = MyPageNumberPagination

举例:

偏移分页: LimitOffsetPagination

导入模块:

from rest_framework.pagination import LimitOffsetPagination

page.py

class MyLimitOffsetPagination(LimitOffsetPagination):
# 默认每页显示数据为几条
default_limit = 3
# 当前页获取几条数据: ?limit=3 , 如果没有写使用默认 default_limit
limit_query_param = 'limit'
# ?limit=3&offset=2 从第二条数据开始但不包括第二条数据向下展示三条。
offset_query_param = 'offset'
# 最大显示条数
max_limit = 5

views.py

from rest_framework.generics import ListAPIView
from rest_framework.viewsets import ViewSetMixin
from .filter import MyFilter
from .page import MyPageNumberPagination,MyLimitOffsetPagination
# 自定义过滤
class BookAPIView(ViewSetMixin, ListAPIView):
queryset = Books.objects.all()
serializer_class = BookSerializers
filter_backends = [MyFilter, ]
# 分页只要一种方式,必须继承GenericAPIView类
pagination_class = MyLimitOffsetPagination

CursorPagination,一般用作体量非常大或者手机端的查询。

作用:只能选择上一页和下一页,不能指定某一页,但是查询速度快。大数据量和app分页不需要指定指定跳转到第几页,下拉加载下一页即可。

page.py

from rest_framework.pagination import CursorPagination
class MyCursorPagination(CursorPagination):
# 默认每页显示条数
page_size = 3
# 查询关键字?cursor=cD0z
cursor_query_param = 'cursor'
# 排序,正向或者倒序
ordering = 'id'

views.py

from rest_framework.generics import ListAPIView
from rest_framework.viewsets import ViewSetMixin
from .filter import MyFilter
from .page import MyCursorPagination
class BookAPIView(ViewSetMixin, ListAPIView):
queryset = Books.objects.all()
serializer_class = BookSerializers
filter_backends = [MyFilter, ]
# 分页只要一种方式,必须继承GenericAPIView类
pagination_class = MyCursorPagination

总结:PageNumberPagination,LimitOffsetPagination,CursorPagination。三者区别。

PageNumberPagination,LimitOffsetPagination: 可以从中间位置获取到某一页,CursorPagination分页只能获取上一页和下一页。

PageNumberPagination,LimitOffsetPagination:获取到某一页时,需要从开始过滤到要取的页面数的数据。CursorPagination在取到某一页时不用过滤之前的数据。

分类: drf

posted @   冀未然  阅读(17)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示