Django-GenericAPIView


前言

GenericAPIView视图是继承自APIView视图的,支持APIView视图的所有功能,还支持过滤、分页、排序等功能。

一、queryset和serializer_class属性

GenericAPIView提供了两个类属性,queryset(指定查询集)和serializer_class(指定序列化器类)。

# 需继承GenericAPIView
#class ProjectViews(APIView):
class ProjectViews(GenericAPIView):
    queryset = Projects.objects.all()
    serializer_class = serializers.ProjectModelSerializer
    
    def get(self, request: Request):
    	...
    	# 一般不用self.queryset获取,而使用self.get_queryset获取类属性queryset
    	queryset = self.get_queryset()
    	# 同上,使用self.get_serializer获取类属性serializer_class
    	self.get_serializer(instance=queryset)

二、get_object方法

GenericAPIView提供get_object方法。其作用与下面的代码类似。

  • 注意:GenericAPIView提供的get_object不需要传pk参数。
def get_object(self, pk):
    try:
        return Projects.objects.get(id=pk)
    except Exception:
        raise Http404

三、过滤

3.1 指定过滤器

方式一:在全局指定

在Django项目的setting.py文件中指定过滤器。
DEFAULT_FILTER_BACKENDS的值为过滤器的引用,获取方式如下图:
在这里插入图片描述
把上面获取到的引用复制给DEFAULT_FILTER_BACKENDS作为值,此时我们的Django项目就支持过滤功能了。

REST_FRAMEWORK = {
    
    
	...
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.SearchFilter'],
}

方式二:在视图中指定

在视图类中添加filter_backends参数用来指定过滤器,视图类中的过滤器优先级高于全局。

from rest_framework.filters import SearchFilter

class ProjectViews(GenericAPIView):
    ...
    filter_backends = [SearchFilter]

3.2 修改视图类添加过滤功能

  • 在视图类中添加search_fields参数用来指定需要过滤的字段。
    • 如果不指定,会对所有read_only=True的参数进行过滤。
    • 在字段前面添加前缀指定过滤方法。
      • 默认的过滤方法为icontain(忽略大小写的包含查询)
      • 字段前加’^'为 ‘istartswith’(以…开头)
      • 字段前加’='为 ‘iexact’(忽略大小写的相等)
      • 字段前加’$'为 ‘iregex’(忽略大小写的正则)
  • 在方法中使用self.filter_queryset(self.get_queryset())获取过滤后的查询集。
class ProjectViews(GenericAPIView):
    queryset = Projects.objects.all()
    serializer_class = serializers.ProjectModelSerializer
    search_fields = ['^name', '=leader']
    
    def get(self, request: Request):
        # filter_queryset需要传递查询集对象作为参数
        queryset = self.filter_queryset(self.get_queryset())

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

此时,前端传query string参数?search=xxx就可以使用过滤功能了。

3.2.1 修改query string参数的默认key“search”

在Django项目的setting.py文件中指定搜索默认的key。

REST_FRAMEWORK = {
    
    
	...
    'SEARCH_PARAM': 's',
}

此时,前端需要传query string参数?s=xxx才能使用过滤功能。

四、排序

4.1 指定过滤器

方式一:在全局指定

在Django项目的setting.py文件中指定过滤器。
DEFAULT_FILTER_BACKENDS的值为过滤器的引用,获取方式如下图:
在这里插入图片描述

把上面获取到的引用复制给DEFAULT_FILTER_BACKENDS作为值,此时我们的Django项目就支持排序功能了。

REST_FRAMEWORK = {
    
    
	...
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.OrderingFilter'],
}

方式二:在视图中指定

在视图类中添加filter_backends参数用来指定过滤器,视图类中的过滤器优先级高于全局。

from rest_framework.filters import OrderingFilter

class ProjectViews(GenericAPIView):
    ...
    filter_backends = [SearchFilter, OrderingFilter]

4.2 修改视图类添加过滤功能

  • 在视图类中添加ordering_fields参数用来指定需要过滤的字段(ordering_fields='__all__'可以指定排序字段为所有字段)。
  • 可以添加ordering参数用来指定默认排序字段,如果前端未指定排序字段,会使用此字段进行排序。
class ProjectViews(GenericAPIView):
    queryset = Projects.objects.all()
    serializer_class = serializers.ProjectModelSerializer
	# 指定需要过滤的字段
    ordering_fields = ['id', 'name', 'leader']
    # 指定默认排序字段
    ordering = ['name']
    ...

此时,前端传query string参数?ordering=xxx就可以使用过滤功能了。

  • 前端可以在字段前添加“-”,进行逆序排序,默认为升序。
  • 在前端可以指定多个排序字段,每个排序字段之间使用逗号分隔,如:?ordering=-id,name

4.2.1 修改query string参数的默认key“ordering”

在Django项目的setting.py文件中指定搜索默认的key。

REST_FRAMEWORK = {
    
    
	...
    'ORDERING_PARAM': 'o',
}

此时,前端需要传query string参数?o=xxx才能使用过滤功能。

五、分页

5.1 指定分页引擎类

在Django项目的setting.py文件中指定过滤器和每页最大数量。
DEFAULT_FILTER_BACKENDS的值为过滤器的引用,获取方式如下图:
在这里插入图片描述把上面获取到的引用复制给DEFAULT_PAGINATION_CLASS作为值,此时我们的Django项目就支持分页功能了。

REST_FRAMEWORK = {
    
    
	...
	# 指定分页引擎类
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    # 指定每一页显示的最大数据条数
    'PAGE_SIZE': 4,
}

5.2 修改视图类添加分页功能

class ProjectViews(GenericAPIView):
    queryset = Projects.objects.all()
    serializer_class = serializers.ProjectModelSerializer
    filter_backends = [SearchFilter, OrderingFilter]

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

    def get(self, request: Request):
        queryset = self.filter_queryset(self.get_queryset())

        # 使用paginate_queryset方法,进行分页操作;需要接收查询集参数;如果返回的数据为空,说明不进行分页操作,否则需要进行分页操作
        page = self.paginate_queryset(queryset)
        if page is not None:
        	# 调用get_serializer,将page作为参数传给instance
            serializer = self.get_serializer(instance=page, many=True)
            # 分页必须调用get_paginated_response方法返回
            return self.get_paginated_response(serializer.data)

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

此时,前端传query string参数“?page=xxx”就可以使用分页功能了。

5.3 前端动态指定每一页的数据条数

在公共模块中新建一个pagination.py文件,存放相关代码。

from rest_framework.pagination import PageNumberPagination as _PageNumberPagination

# 继承rest_framework的PageNumberPagination类,并将类名写为一样的
class PageNumberPagination(_PageNumberPagination):
    # 指定默认每一页显示的数据条数
    page_size = 3
    # 前端用于指定页号的查询字符串参数名称
    page_query_param = 'p'
    # 指定前端用于指定页号的查询字符串参数的描述
    page_query_description = '获取的页码'
    # 只要设置了page_size_query_param,那么前端就支持指定获取每一页的数据条数,前端传“?s=8”就可以将每一页的数据设置为8条
    page_size_query_param = "s"
    # 前端用于指定每一页的数据条数,查询字符串参数的描述
    page_size_query_description = '每一页数据条数'
    # 设置每一页最大的数据条数
    max_page_size = 100

	# 重写父类的方法给返回的数据增加页号字段
    def get_paginated_response(self, data):
        # 调用父类的实现
        response = super().get_paginated_response(data)
        # 增加页号字段
        response.data['current_num'] = self.page.number
        # 返回新增后的字典
        return response

想要只让当前视图支持上面自定义分页功能,可在当前视图中设置分页引擎。(需导入上面的类)

class ProjectViews(GenericAPIView):
    ...
    pagination_class = PageNumberPagination
    ...

总结

GenericAPIView主要的属性

queryset: 指定查询集,如:queryset = Projects.objects.all()
serializer_class: 指定序列化器类,如:serializer_class = serializers.ProjectModelSerializer

GenericAPIView主要的方法

get_queryset(): 获取类属性中指定的查询集。
get_serializer(): 获取类属性中指定的序列化器类。
get_serializer_class(): 返回序列化器类,调用get_serializer()时会调用这个方法,默认返回serializer_class。
filter_queryset(): 使用过滤器对数据进行过滤,需要接收查询集参数。
paginate_queryset(): 对传入的数据进行分页操作,需要接收查询集参数。
get_paginated_response(): 为给定的输出数据返回一个分页样式的’ Response '对象,一般传参为serializer.data。
get_object():根据pk获取单个数据。

猜你喜欢

转载自blog.csdn.net/qq_33537936/article/details/113646978
今日推荐