上一章:

六、DRF框架APIView–request&response解析器&渲染器_做测试的喵酱的博客-CSDN博客

下一章:

一、GenericAPIView介绍

APIView 继承 View

GenericAPIView 继承 APIView。

GenericAPIView 功能

GenericAPIView的引用

from rest_framework.generics import GenericAPIView

二、GenericAPIView的使用

1、视图类,需要继承GenericAPIView

2、需要定义属性, queryset 查询集、  serializer_class 指定当前视图实例方法需要使用序列化器类

3、在函数中,

  1. 调用queryset 查询方法self.get_queryset()
  2. 调用查询集中单个实例对象    project_obj = self.get_object()
  3. 调用序列化器实例 方法serializer = self.get_serializer(instance=project_obj)

class ProjectsView(GenericAPIView):
    """
    继承GenericAPIView父类(GenericAPIView子类a.具备View的所有特性
    b.具备了APIView中的认证授权限流功能
    c.还支持对于获取列表数据接口的功能:搜索、排序、分页
    """
    # 一旦继承GenericAPIView之后,往往需要指定querysetserializer_class属性
    # queryset指定当前视图实例方法需要使用的查询集对象
    queryset = Projects.objects.all()
    # serializer_class指定当前视图实例方法需要使用的序列化器类
    serializer_class = ProjectSerilizer

三、GenericAPIView实现搜索

GenericAPIView实现搜索

3.1、在Djangosetting文件设置搜索引擎

在Djangosetting文件中,REST_FRAMEWORK 下,在全局DEFAULT_FILTER_BACKENDS指定使用的过滤引擎类(SearchFilter为搜索引擎类)

REST_FRAMEWORK = {
 

    # 1、在全局DEFAULT_FILTER_BACKENDS指定使用的过滤引擎类(SearchFilter为搜索引擎类)
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.SearchFilter',
                                'rest_framework.filters.OrderingFilter'],
    # 可以全局使用SEARCH_PARAM修改前端过滤查询字符串参数名称默认search)
    # 'SEARCH_PARAM': 'se',

    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 3,
}

3.2、视图类引用搜索引擎

1、视图类属性设置需要搜索字段

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

搜索类型, 使用icontains查询类型作为过滤类型。(忽略大小写

指定查询类型:

  可以字段名称前添加相应符号指定查询类型

默认,是icontains查询类。忽略大小写包含 search_fields = [‘id‘, ‘name‘, ‘leader‘]

^以什么开头,如以name开头数据

=完全命中,如leader字段

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

2、获取经过过滤的查询集结果

        # filter_queryset对查询对象进行过滤操作
        queryset = self.filter_queryset(self.get_queryset())

3、搜索演示

http://127.0.0.1:8000/projects/?search=x项目

注意:

4、修改搜索关键词

默认搜索关键词,是search

想要自定义搜索关键词,在setting文件中,通过 ‘SEARCH_PARAM’ 实现

REST_FRAMEWORK = {
 

    # 1、在全局DEFAULT_FILTER_BACKENDS指定使用的过滤引擎类(SearchFilter为搜索引擎类)
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.SearchFilter',
                                'rest_framework.filters.OrderingFilter'],
    # 可以全局使用SEARCH_PARAM修改前端过滤查询字符串参数名称(默认为search)
    'SEARCH_PARAM': 'mysearch',

    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 3,
}

 http://127.0.0.1:8000/projects/?mysearch=x项目

3.3、视图类中定义搜索引擎

1、背景

在setting中,定义的是项目全局搜索引擎

如果我想,只在某几个视图类中,使用搜索引擎,则需要在对应的视图类中设置索引擎。

2、视图类中 设置引擎

优先级高于全局设置引擎


    from rest_framework import filters


    class ProjectsView(GenericAPIView):

    # filter_backends在继承了GenericAPIView的类视图中指定使用的过滤引擎类(搜索、排序)
    # 优先级高于全局
    filter_backends = [filters.SearchFilter]

四、GenericAPIView实现(搜索结果的)排序功能

想要对搜索结果进行排序,需要使用排序引擎OrderingFilter

4.1 设置排序引擎OrderingFilter

设置排序,引擎,有两种方式,1、在setting中设置全局引擎,对整个项目适用

2、在视图类中设置局部引擎,对当前的视图类生效

4.1.1 在setting中设置全局引擎

注意,这里使用的是字符串

REST_FRAMEWORK = {
  
    # 1、在全局DEFAULT_FILTER_BACKENDS指定使用的过滤引擎类(SearchFilter为搜索引擎类)
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.SearchFilter',
                                'rest_framework.filters.OrderingFilter'],

4.1.2 在视图类中设置局部引擎

from rest_framework import filters
class ProjectsView(GenericAPIView):

    # 一旦继承GenericAPIView之后,往往需要指定queryset、serializer_class类属性
    # queryset指定当前类视图的实例方法需要使用的查询集对象
    queryset = Projects.objects.all()
    # serializer_class指定当前类视图的实例方法需要使用的序列化器类
    serializer_class = ProjectSerilizer

    # filter_backends在继承了GenericAPIView的类视图中指定使用的过滤引擎类(搜索、排序)
    # 优先级高于全局
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]

4.2视图类中,设置排序字段 

想要支持哪些字段的排序,需要在视图类中,定义 ordering_fields 。

如下,设置支持idnameleader的排序

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

4.3 查询结果 

  # filter_queryset对查询对象进行过滤操作
  queryset = self.filter_queryset(self.get_queryset())

4.4 查询演示 ,查询排序关键字ordering

1、默认升序

查询name为张三,并且将查询结果按照name排序

http://127.0.0.1:8000/projects/?search=张三&ordering=name

2、降序排序,在字段名前加上-

如按照name降序排序,-name

http://127.0.0.1:8000/projects/?search=张三&ordering=-name

3、按照多个字段排序

多个字段排序,使用逗号隔开。

按照name与leader排序,name降序leader升序

http://127.0.0.1:8000/projects/?search=张三&ordering=-name,leader

五、分页引擎 PageNumberPagination

5.1 设置分页引擎PageNumberPagination

5.1.1 在setting中,设置全局分页引擎PageNumberPagination

REST_FRAMEWORK = {

    # 1、在全局DEFAULT_FILTER_BACKENDS指定使用的过滤引擎类(SearchFilter为搜索引擎类)
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.SearchFilter',
                                'rest_framework.filters.OrderingFilter'],
    # 可以在全局使用SEARCH_PARAM修改前端过滤查询字符参数名称(默认为search)
    # 'SEARCH_PARAM': 'se',

    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 8,
}

分页引擎:

 ‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination‘,

一页个数
   ‘PAGE_SIZE’: 10,

5.1.2 在视图类中,设置局部分页引擎PageNumberPagination

1、在视图类的py文件中,引入PageNumberPagination

from rest_framework.pagination import PageNumberPagination

2、 在视图类的属性汇总,指定分页引擎

   # 可以在类视图中指定分页引擎类,优先级高于全局
    pagination_class = PageNumberPagination

 

5.2 视图类中设置分页

   def get(self, request: Request):
    

        # filter_queryset对查询对象进行过滤操作
        queryset = self.filter_queryset(self.get_queryset())
       
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(instance=page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(instance=queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

1、先判断,(请求是否需要进行分页处理

page = self.paginate_queryset(queryset)

没有做分页处理时,page值为None。

做了分页处理page值为分页后的查询集

2、对分页的数据进行处理

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(instance=page, many=True)
            return self.get_paginated_response(serializer.data)

3、没有做分页处理时(page为none时),返回正常的查询集结果。

六、自定义分页功能(支持用户指定一页数据个数

在五中,用户请求,只能指定页码,但是不能指定一页多少条数据。

我们通过重写PageNumberPagination类实现

6.1 重写PageNumberPagination类

utils文件夹下,新建文件pagination.py通过继承的方式重写PageNumberPagination类。

pagination.py

from rest_framework.pagination import PageNumberPagination as _PageNumberPagination


class PageNumberPagination(_PageNumberPagination):
    # 指定默认每一页显示5条数据
    page_size = 5

    # 前端用于指定页码的查询字符串参数名称
    page_query_param = 'page'
    # 前端用于指定页码的查询字符串参数描述
    page_query_description = '获取的页码'

    # 前端用于指定每一页显示数据条数,查询字符串参数名称
    page_size_query_param = 'page_size'
    page_size_query_description = '每一页数据条数'

    max_page_size = 50
    invalid_page_message = '无效页码'

1、通过继承的方式重写PageNumberPagination

2、我们定义的类,名称也想叫做 PageNumberPagination 。解决办法:先引入父类PageNumberPagination,然后再给他取一个别名

from rest_framework.pagination import PageNumberPagination as _PageNumberPagination


class PageNumberPagination(_PageNumberPagination):

3、设置一页数据个数

    # 指定默认每一页显示5条数据
    page_size = 5

4、设置页码关键字

# 前端用于指定页码的查询字符串参数名称
page_query_param = 'page'

‘page’是自定义的,可以换成其他字符串 

5、设置指定一页数据个数关键字

    # 前端用于指定每一页显示的数据条数,查询字符串参数名称
    page_size_query_param = 'page_size'
    page_size_query_description = '每一页数据条数'

‘page_size’是自定义的,可以换成其他字符串 

6、指定一页多少数据的最大限制

max_page_size = 50
invalid_page_message = '无效页码'

 6.2 在视图类中使用自定义的PageNumberPagination类

1、先在py文件中,引入 自定义的PageNumberPagination类

from utils.pagination import PageNumberPagination

2、在视图类中,设置 PageNumberPagination类

    # 可以在类视图中指定分页引擎类,优先级高于全局
    pagination_class = PageNumberPagination

视图类的整体代码如下:

class ProjectsView(generics.ListCreateAPIView):

    queryset = Projects.objects.all()
    serializer_class = ProjectModelSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['=name', '=leader', '=id']
    ordering_fields = ['id', 'name', 'leader']

    # 可以在类视图中指定分页引擎类,优先级高于全局
    pagination_class = PageNumberPagination

 6.3 请求演示

请求第2页数据,设置一页6条数

http://127.0.0.1:8000/projects/?page=2&page_size=6

七、其他筛选过滤方式

官网

Filtering – Django REST framework中文站点

DjangoFilterBackend(Django过滤后端)

django-filter包含一个为REST framework提供高度定制字段过滤的DjangoFilterBackend类。

要使用DjangoFilterBackend,首先要先安装django-filter

pip install django-filter

现在,你需要将filter backend 添加到你django projectsettings中:

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

或者你也可以将filter backend添加一个单独的viewviewSet中:

    from django_filters.rest_framework import DjangoFilterBackend

    class UserListView(generics.ListAPIView):
        ...
        filter_backends = [DjangoFilterBackend]

如果只需要简单的根据是否相等的过滤,则可以在视图或视图集上设置filterset_fields属性列出要过滤的字段集合

class ProductList(generics.ListAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['category', 'in_stock']

这将自动给定的字段创建一个FilterSet类,并允许你发出如下请求

http://example.com/api/products?category=clothing&in_stock=True

对于更高级的过滤要求,你可以指定视图应使用的FilterSet类。你可以在django-filter文档阅读有关FilterSets的更多信息。还建议阅读有关DRF集成的部分。

八、重写返回值

GenericAPIView 的返回值,使用的是 return self.get_paginated_response(serializer.data)。

返回结果,包含字段为

   {
        "count":xxx,
        "next":xxxx,
        "previous":xxx,
        "reslut": 数据值
    }

count为数据总数

next 为下一页地址

previous 是上一页地址

如果这些字段不满足我们的需求,我们需要在返回结果中,添加当前页面的页码、最大的页码,通过重写 PageNumberPagination类的 get_paginated_response 方法实现

from rest_framework.pagination import PageNumberPagination as _PageNumberPagination


class PageNumberPagination(_PageNumberPagination):
    # 指定默认每一页显示5条数据
    page_size = 5

    # 前端用于指定页码的查询字符串参数名称
    page_query_param = 'page'
    # 前端用于指定页码的查询字符串参数描述
    page_query_description = '获取的页码'

    # 前端用于指定每一页显示的数据条数,查询字符串参数名称
    page_size_query_param = 'page_size'
    page_size_query_description = '每一页数据条数'

    max_page_size = 50
    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

再使用PageNumberPagination 的视图模块中,引入自定义的类,而不是框架自带的PageNumberPagination类。

原文地址:https://blog.csdn.net/qq_39208536/article/details/130903318

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_34010.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注