• drf群查接口之分页器与过滤器


    分页器的使用详解

    rest_framework.mixins.py
    # 分页器一般用于群查接口
    class ListModelMixin:
        """
        List a queryset.
        """
        def list(self, request, *args, **kwargs):
            queryset = self.filter_queryset(self.get_queryset())
    		
            # 先过滤,后分页
            # self.paginate_queryset由继承GenericAPIView而来
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
    
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
    
    GenericAPIView类
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
    
    @property
    def paginator(self):
        """
            The paginator instance associated with the view, or `None`.
            """
        if not hasattr(self, '_paginator'):
            if self.pagination_class is None:
                self._paginator = None
                else:
                    self._paginator = self.pagination_class()
                    return self._paginator
    
    
    def paginate_queryset(self, queryset):
        """
            Return a single page of results, or `None` if pagination is disabled.
            """
        if self.paginator is None:
            return None
        # 调用View视图类中配置的paginator的paginate_queryset方法
        # paginatior是一个方法属性来反射获取pagination_class
        return self.paginator.paginate_queryset(queryset, self.request, view=self)
    

    drf自带的几种分页器

    from rest_framework.pagination import PageNumberPagination as DrfPageNumberPagination
    
    class PageNumberPagination(DrfPageNumberPagination):
        # 默认一页显示的条数
        page_size = 2
        # url中携带页码的key
        page_query_param = 'page'
        # url中用户携带自定义一页条数的key
        page_size_query_param = 'page_size'
        # 用户最大可自定义一页的条数
        max_page_size = 3
    
    
    from rest_framework.pagination import LimitOffsetPagination as DrfLimitOffsetPagination
    class LimitOffsetPagination(DrfLimitOffsetPagination):
        # 默认一页显示的条数
        default_limit = 2
        # url中用户携带自定义一页条数的key
        limit_query_param = 'limit'
        # url中用户携带自定义偏移条数的key
        offset_query_param = 'offset'
        # 用户最大可自定义一页的条数
        max_limit = 2
    
    
    from rest_framework.pagination import CursorPagination as DrfCursorPagination
    class CursorPagination(DrfCursorPagination):
        # 默认一页显示的条数
        page_size = 2
        # url中携带页码的key(编码后的结果)
        cursor_query_param = 'cursor'
        # url中用户携带自定义一页条数的key
        page_size_query_param = 'page_size'
        # 用户最大可自定义一页的条数
        max_page_size = 3
        # 游标分页器的特殊点:
        # 1)如果视图类没有配 排序过滤组件filter_backends = [OrderingFilter],采用 ordering 设置的作为默认排序规则
        # 2)如果视图类配了 排序过滤组件filter_backends = [OrderingFilter],url请求必须带上ordering排序规则,因为默认排序规则失效
        # 注:因为游标分页是基于排序后结果上的分页
        ordering = '-price'
    

    过滤器

    过滤器中有自带的排序组件
    """ORDERING_PARAM
    排序组件
    1)在视图文件views.py中导入drf的搜索组件
    from rest_framework.filters import OrderingFilter
    
    2)将搜索组件配置给群查接口视图类的filter_backends
    filter_backends = [OrderingFilter]
    
    3)配置视图类关联的Model表允许排序的字段
    ordering_fields = ['id', 'price']
    
    4)前台访问该群查接口,采用拼接参数方式用search关键字将搜索目标提供给后台
    http://127.0.0.1:8000/course/free/?ordering=price,-id  # 按price升序,如果price相同,再按id降序
    """
    
    自定义过滤组件
    """
    自定义过滤器
    1)自定义类实现filter_queryset方法即可,接收request, queryset, view参数
    
    2)制定过滤条件,将过滤成功后的queryset返回即可,如果过滤失败,返回原样的queryset
    
    3)将自定义过滤类配置给群查视图类的filter_backends
    """
    
    filter.py
    # 前台接口:/course/free/?count=2 ,代表只对前台返回2条数据
    class CountFilter:
        def filter_queryset(self, request, queryset, view):
            count = request.query_params.get('count', None)
            try:
                # TODO: 切片后的queryset不能再做ORM Q查询,如何实现queryset切片,现在再过滤时后配置
                # 结论:drf的搜索组件和排序组件都是建立在表的所有数据基础上的过滤规则,所以该自定义过滤类在视图类配置中
                # filter_backends = [SearchFilter, OrderingFilter, CountFilter] 必须在前两者之后
                return queryset[:int(count)]
            except:
                return queryset
    
    搜索过滤
    '''
    # 分页组件:基础分页(采用)、偏移分页、游标分页(了解)
    from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
    from . import pagination
    
    # 过滤组件:搜索功能、排序功能
    from rest_framework.filters import SearchFilter, OrderingFilter
    from .filters import CountFilter
    class CourseViewSet(GenericViewSet, ListModelMixin):
        queryset = models.Course.objects.filter(is_delete=False, is_show=True).all()
        serializer_class = serializers.CourseSerializer
    
        # 分页组件
        # 方法一:直接使用drf分页类,在视图类中完成分页类的必要配置
        # pagination_class = PageNumberPagination
        # PageNumberPagination.page_size = 1
    
        # 方法二:自定义分页类继承drf分页类,在自定义分页类中完成配置,视图类中使用自定义分页类
        # 基础分页器
        # pagination_class = pagination.PageNumberPagination
        # 偏移分页器,没有固定页码,自定义从偏移量开始往后查询自定义条数
        # pagination_class = pagination.LimitOffsetPagination
        # 游标分页器
        # pagination_class = pagination.CursorPagination
    
        # 过滤组件:实际开发,有多个过滤条件时,要把优先级高的放在前面
        filter_backends = [SearchFilter, OrderingFilter, CountFilter]
        # 参与搜索的字段
        search_fields = ['name', 'id']
    
        # 允许排序的字段
        ordering_fields = ['id', 'price']
    
    '''
    

    high_mark和low_mark控制切queryset的大小

    queryset.query.high_mark = None
    queryset.query.low_mark = 0
    
    # 实际是对queryset的克隆,修改low_mark=1,high_mark=10
    new_queryset = queryset[1,10]
    
    
    分类过滤和区间过滤

    fitler.py

    class CourseFilterSet(filterset.FilterSet):
        max_price = filters.NumberFilter(field_name='price', lookup_expr='lte')
        min_price = filters.NumberFilter(field_name='price', lookup_expr='gte')
        class Meta:
            model = models.Course
            fields = ['max_price', 'min_price','course_category']
    
    views.py
    class CourseViewSet(viewsets.GenericViewSet, mixins.ListModelMixin):
        queryset = models.Course.objects.filter(is_delete=False, is_show=True)
        serializer_class = serializers.CourseModelSerializer
        # 过滤
        filter_backends = [DjangoFilterBackend]
        # max_price=100&min_price=20&course_category=1 
        # 为django-filter配置,区间分页
        filterset_class = CourseFilterSet
    
        
    # 阅读django-filter的源码可以发现直接在view视图里声明filterset_fields=['course_category']也可以完成分类过滤
    
  • 相关阅读:
    MySQL的简单使用
    GoLang基础—变量、数据类型、常量
    网络编程
    前端
    并发编程
    Pyspider的简单介绍和初使用
    Python 生成requirements文件以及使用requirements.txt部署项目
    redis简单了解与简单使用
    腾讯云短信接口完成验证码功能
    git的基础使用
  • 原文地址:https://www.cnblogs.com/Ghostant/p/12548399.html
Copyright © 2020-2023  润新知