【DRF】*GenericAPIView提供的分页、搜索过滤、搜索排序功能(5.25)

     阅读:23

一、搜索过滤
采用的方式:使用icontains查询类型作为过滤类型

tip:双击shift可以搜索想要找的文件
在这里插入图片描述

1、settings.py文件REST_FRAMEWORK 中指定搜索引擎类:

REST_FRAMEWORK = {
    #指定搜索引擎类
    'DEFAULT_FILTER_BACKENDS':['rest_framework.filters.SearchFilter']
}

特别注意1:全局配置文件中指定搜索引擎类,所有继承GenericAPIView的类视图中的获取列表数据的接口都具有搜索的功能
2、在继承了GenericAPIView相应的类视图中应用,指定能够支持搜索过滤的字段

search_fields=['name','leader']

class ProjectsView(GenericAPIView):
    queryset = Projects.objects.all()
    serializer_class = ProjectsSerializer

    search_fields=['name','leader']

    def get(self, request):

        queryset=self.filter_queryset(self.get_queryset())

        serialzer=self.get_serializer(instance=queryset,many=True)
        return Response(serialzer.data,status=status.HTTP_200_OK)

    def post(self, request):
        serializer=self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 响应结果
        return Response(serializer.data,status=status.HTTP_201_CREATED)

特别注意2:实例方法中必须调用filter_queryset方法,并且要传入查询集对象

3、搜索字段默认为search,rest_framework配置文件settings中默认指定;
在这里插入图片描述
在这里插入图片描述

4、如果修改可以在自己项目的settings.py文件中重新定义

在这里插入图片描述
在这里插入图片描述

5、可以在字段名称前加相应的符号,指定查询类型,

6、^:以什么开头,=:包含,$:正则匹配

7、想要在特定的视图类中进行过滤功能

filter_backends在继承了GenericAPIView的类视图中指定使用的过滤引擎类优先级高于全局

filter_backends = [filters.SearchFilter]

class ProjectsView(GenericAPIView):
    queryset = Projects.objects.all()
    serializer_class = ProjectsSerializer
    
    filter_backends = [filters.SearchFilter]

    search_fields=['name','leader']

    def get(self, request):

        queryset=self.filter_queryset(self.get_queryset())

        serialzer=self.get_serializer(instance=queryset,many=True)
        return Response(serialzer.data,status=status.HTTP_200_OK)

    def post(self, request):
        serializer=self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 响应结果
        return Response(serializer.data,status=status.HTTP_201_CREATED)

二、排序过滤(通过添加django-fitlter扩展来增强⽀持)
1、虚拟环境中安装相应模块

pip insall django-filter

2、新应⽤模块注册项⽬中

INSTALLED_APPS = [ 
	... 
	'django_filters', # 需要注册应⽤,]

3、全局配置过滤器后端(全局生效)

REST_FRAMEWORK = { 
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']}

4、视图中局部配置过滤器后端

filter_backends = [DjangoFilterBackend]

5、指定过滤字段

filterset_fields = ['name','leader']

6、前端访问既可以使⽤两个参数进⾏过滤也可以使⽤其中⼀个参数进⾏过滤
在这里插入图片描述

三、排序过滤

1、在全局’DEFAULT_FILTER_BACKENDS’指定使用的排序(OrderingFilter为排序类)
在这里插入图片描述

2、 filter_backends在继承了GenericAPIView的类视图中指定使用的过滤引擎类(搜索过滤、排序过滤),优先级高于全局

class ProjectsView(GenericAPIView):
    queryset = Projects.objects.all()
    serializer_class = ProjectsSerializer

    filter_backends = [filters.SearchFilter,filters.OrderingFilter]

    search_fields=['name','leader','id']
    ordering_fields=['name','leader','id']

    def get(self, request):

        queryset=self.filter_queryset(self.get_queryset())

        serialzer=self.get_serializer(instance=queryset,many=True)
        return Response(serialzer.data,status=status.HTTP_200_OK)

    def post(self, request):
        serializer=self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 响应结果
        return Response(serializer.data,status=status.HTTP_201_CREATED)

ordering_fields类属性指定模型类中允许前端进行排序的字段名称
前端默认可以使用ordering作为排序功能查询字符串参数名称,默认该字段为升序
如果在字段名称前添加“-”,代表该字段降序
如果指定多个排序字段,使用英文逗号进行分割

在这里插入图片描述
四、分页

1、全局指定分页引擎类(全局生效)
'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination'
2、指定分页条数,PAGE_SIZE:指定每页默认展示3条数据
'PAGE_SIZE':3

REST_FRAMEWORK = {
    #指定搜索引擎类
    'DEFAULT_FILTER_BACKENDS':['rest_framework.filters.SearchFilter',
                               'rest_framework.filters.OrderingFilter'],
    #'SEARCH_PARAM': 'se',
    
    #指定分页引擎类
    'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination'
}

3、调用paginate_queryset方法对查询集对象进行分页,(不能传模型对象,因为模型对象只有一条数据,不做分页操作)
在这里插入图片描述

调用get_paginated_response方法,将序列化之后的数据进行分页,并返回Response响应

5、如果前端获取指定的页码以及页码中一定的数据,操作如下

a、在utils文件中新建pagination.py文件
在这里插入图片描述

b、在pagination.py中重写父类的方法

from rest_framework.pagination import PageNumberPagination as _PageNumberPagination


class PageNumberPagination(_PageNumberPagination):
    #指定默认每一页显示3条数据
    page_size=2
    #前端用于指定页码的查询查询字符串参数名称
    page_query_param = 'page'
    #前端用于指定页码的查询查询字符串参数描述
    page_query_description='获取的页码'
    #前端用于指定每一页显示的数据条数查询字符串参数名称
    page_size_query_param = 'ss'
    page_size_query_description='每一页数据条数'
    #最大限制50条
    max_page_size = 50
    last_page_strings = ('last',)
    invalid_page_message='无效页码'

c、可以在特定的类视图下指定分页引擎类,高于全局

class ProjectsView(GenericAPIView):
    queryset = Projects.objects.all()
    serializer_class = ProjectsSerializer

    filter_backends = [filters.SearchFilter,filters.OrderingFilter,DjangoFilterBackend]
    search_fields = ['name', 'leader', 'id']
    ordering_fields = ['name', 'leader', 'id']
    filterset_fields = ['name', 'leader']
    
    pagination_class = PageNumberPagination

例如:每页展示2条数据,展示第4页
在这里插入图片描述

五、实现响应数据中展示当前页、总页数

重写get_paginated_response(self, data):方法

from rest_framework.pagination import PageNumberPagination as _PageNumberPagination
from rest_framework.response import Response


class PageNumberPagination(_PageNumberPagination):
    #指定默认每一页显示3条数据
    page_size=2
    #前端用于指定页码的查询查询字符串参数名称
    page_query_param = 'page'
    #前端用于指定页码的查询查询字符串参数描述
    page_query_description='获取的页码'
    #前端用于指定每一页显示的数据条数查询字符串参数名称
    page_size_query_param = 'ss'
    page_size_query_description='每一页数据条数'
    #最大限制50条
    max_page_size = 50
    last_page_strings = ('last',)
    invalid_page_message='无效页码'


    def get_paginated_response(self, data):
        response=super().get_paginated_response(data)
        response.data['current_num']=self.page.number
        response.data['max_num']=self.page.paginator.num_pages
        return response

在这里插入图片描述