排序、过滤、分页

排序、过滤、分页

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

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

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

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  # 分页方式只能选择一种
posted @   Formerly0^0  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示