排序、过滤、分页
1. 排序
1.1 使用条件
# 必须是查询所有接口--》restful规范中:地址栏中带过滤条件
http://127.0.0.1:8008/app01/api/v1/books/?ordering=price
# 必须是继承 GenericAPIView 的视图类---》继承APIView是不能这么配置的
1.2 使用排序
# 1.引入相关排序相关模块
from rest_framework.filters import OrderingFilter
class BookView(GenericViewSet, ListCreateAPIView, RetrieveUpdateAPIView):
queryset = Book_new.objects.all()
serializer_class = Book_newSerializer
# 2.添加 OrderingFilter,表示使用order进行排序
filter_backends = [OrderingFilter]
# 3.设置排序字段,可以设置多个
ordering_fields = ['price']
- 前端输入地址
- http://127.0.0.1:8001/app07/books/?ordering=price
- 根据price字段排序,默认升序,如果想要得到倒序,-price即可
1.3 定制返回格式
# 定制返回格式--》重写list--》重写了list,过滤还生效吗?
# 1.如果纯自己写了:不生效
def list(self, request, *args, **kwargs):
books = self.get_queryset()
serializer = self.get_serializer(books, many=True)
return Response({"code": 100, "msg": "成功", "results": serializer.data})
# 2.如果还是使用父类的list方法:生
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
# 3.半自己写:只要有他就会生效 self.filter_queryset()
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
return Response({"code": 100, "msg": "成功", "results": serializer.data})
2. 过滤
2.1 过滤的三种方式
# 过滤跟排序不冲突 三种过滤
# 1.drf内置的过滤模块
# 2.第三方的 django-filter
# 3.自定义过滤,情况比较复杂时用它
2.2 内置的多个字段模糊匹配
2.2.1 使用方式一 单独使用
# 引入模糊匹配相关模块
from rest_framework.filters import SearchFilter
class BookView(GenericViewSet, ListCreateAPIView, RetrieveUpdateAPIView):
queryset = Book_new.objects.all()
serializer_class = Book_newSerializer
# 添加SearchFilter,表示使用SearchFilter进行模糊匹配
filter_backends = [SearchFilter]
# 设置模糊匹配字段
search_fields = ['name']
- 前端输入地址
- http://127.0.0.1:8001/app07/books/?search=奥特曼
- 模糊匹配搜索,name 字段中带有奥特曼的书
2.2.2 使用方式二 与排序一起使用
# 引入模糊匹配相关模块
from rest_framework.filters import SearchFilter
class BookView(GenericViewSet, ListCreateAPIView, RetrieveUpdateAPIView):
queryset = Book_new.objects.all()
serializer_class = Book_newSerializer
# 添加OrderingFilter,SearchFilter
filter_backends = [OrderingFilter,SearchFilter]
# 设置模糊匹配字段和排序字段
ordering_fields = ['price']
search_fields = ['name',]
- 前端输入地址
- http://127.0.0.1:8001/app07/books/?search=奥特曼&ordering=-price
- 根据name字段模糊匹配后,然后根据价格倒叙
2.3 第三方过滤,按名字精准匹配
2.3.1 使用方式
# 1.安装第三方模块:pip3 install django-filter
# 2.视图类中配置
# 2.1 引入模块
from django_filters.rest_framework import DjangoFilterBackend
class BookView(GenericViewSet, ListCreateAPIView, RetrieveUpdateAPIView):
queryset = Book_new.objects.all()
serializer_class = Book_newSerializer
# 添加DjangoFilterBackend,表示用它进行精准匹配
filter_backends = [DjangoFilterBackend]
# 设置精准匹配字段
filterset_fields = ['price']
2.4 自定义过滤类
2.4.1 如何自定义
# 1.定义一个类,继承 BaseFilterBackend
# 在类中重写 filter_queryset方法
2.4.2 过滤类
from django.db.models import Q
# 引入模块
from rest_framework.filters import BaseFilterBackend
# 继承BaseFilterBackend
class CommonFilter(BaseFilterBackend):
# 重写 filter_queryset
def filter_queryset(self, request, queryset, view):
# 完成过滤,返回 qs对象
# 假设查询价格为99的或者书名含梅的数据
price = request.query_params.get('price', None)
name = request.query_params.get('name', None)
if price and name:
print(1)
queryset = queryset.filter(Q(price=price) | Q(name__contains=name))
elif price:
print(2)
queryset = queryset.filter(price=price)
elif name:
print(3)
queryset = queryset.filter(name__contains=name)
return queryset
2.4.3 使用
class BookView(GenericViewSet, ListCreateAPIView, RetrieveUpdateAPIView):
queryset = Book_new.objects.all()
serializer_class = Book_newSerializer
# 添加自定义的过滤模块
filter_backends = [CommonFilter]
3. 分页
# 查询所有接口,后期要分页--》分页跟过滤排序不冲突
# 三种分页方式
# 写个类,继承某个分页类
# 在视图类中配置:必须继承 GenericAPIView
3.1 定义分页类
# 引入分页类
from rest_framework.pagination import CursorPagination,LimitOffsetPagination,PageNumberPagination
# 1.基本分页
class CommonPageNumberPagination(PageNumberPagination):
# 每页显示2条
page_size = 2
# 表示 URL 查询参数中指定页码的参数名,默认为 'page'
# http://127.0.0.1:8001/app07/books/?page=2,代表查询第二页,每页显示2条
page_query_param = 'page'
# 表示 URL 查询参数中指定每页数据条数的参数名,默认为 'size'
# http://127.0.0.1:8001/app07/books/?page=1&size=5 表示查询第一页,每页显示5
page_size_query_param = 'size'
# 每页最多显示10条
max_page_size = 10
# 2.limit offset分页方式 偏移分页
class CommonLimitOffsetPagination(LimitOffsetPagination):
# 默认每页的数据条数为 2 条
default_limit = 2
# 表示 URL 查询参数中指定每页数据条数的参数名,默认为 'limit'。
# http://127.0.0.1:8001/app07/books/?limit=4 一页显示四条
limit_query_param = 'limit'
# 表示 URL 查询参数中指定偏移量的参数名,默认为 'offset'。
# http://127.0.0.1:8001/app07/books/?offset=3 从第3条开始,取两条
# http://127.0.0.1:8001/app07/books/?offset=3&limit=1 从第3条开始,取1条
offset_query_param = 'offset'
# # 最大每页取10条
max_limit = 10
# 游标分页-->必须要排序--》只能取上一页和下一页,不能直接跳转到某一页 效率高, 大数据量 app端使用
class CommonCursorPagination(CursorPagination):
# 表示 URL 查询参数中指定游标的参数名,默认为 'cursor'。
# 当你使用游标分页时,你可以通过修改这个属性来指定在 URL 中用于指定游标的查询参数名。
# http://127.0.0.1:8001/app07/books/?cursor=asfasf
cursor_query_param = 'cursor'
# 每页默认的数据条数为 2 条。
page_size = 2
# 指定分页数据的排序方式,默认按照 'id' 字段排序。
ordering = 'id'
3.2 视图类中使用
class BookView(GenericViewSet, ListCreateAPIView, RetrieveUpdateAPIView):
queryset = Book_new.objects.all()
serializer_class = Book_newSerializer
pagination_class = CommonPageNumberPagination # 分页方式只能选择一种
pagination_class = CommonLimitOffsetPagination # 分页方式只能选择一种
pagination_class = CommonCursorPagination # 分页方式只能选择一种
标签:分页,price,queryset,filter,过滤,books,排序,class
From: https://www.cnblogs.com/Formerly/p/18194269