上一章:
六、DRF框架APIView--request&response解析器&渲染器_做测试的喵酱的博客-CSDN博客
下一章:
一、GenericAPIView介绍
APIView 继承 View
GenericAPIView 继承 APIView。
GenericAPIView 功能:
- a.具备View的所有特性
- b.具备了APIView中的认证、授权、限流功能
- c.还支持对于获取列表数据接口的功能:搜索、排序、分页
GenericAPIView的引用:
from rest_framework.generics import GenericAPIView
二、GenericAPIView的使用
1、视图类,需要继承GenericAPIView
2、需要定义类属性, queryset 查询集、 serializer_class 指定当前类视图的实例方法需要使用的序列化器类
3、在函数中,
- 调用queryset 查询集 方法:self.get_queryset()
- 调用查询集中单个实例对象 project_obj = self.get_object()
- 调用序列化器实例 方法: serializer = self.get_serializer(instance=project_obj)
class ProjectsView(GenericAPIView):"""继承GenericAPIView父类(GenericAPIView子类)a.具备View的所有特性b.具备了APIView中的认证、授权、限流功能c.还支持对于获取列表数据接口的功能:搜索、排序、分页"""# 一旦继承GenericAPIView之后,往往需要指定queryset、serializer_class类属性# queryset指定当前类视图的实例方法需要使用的查询集对象queryset = Projects.objects.all()# serializer_class指定当前类视图的实例方法需要使用的序列化器类serializer_class = ProjectSerilizer
三、GenericAPIView实现搜索
GenericAPIView实现搜索
3.1、在Django的setting文件中 设置搜索引擎
在Django的setting文件中,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查询类型作为过滤类型。(忽略大小写)
指定查询类型:
可以在字段名称前添加相应符号,指定查询类型
- '^': 'istartswith', 以xx开头
- '=': 'iexact',完全命中
- '$': 'iregex',正则
默认,是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项目
注意:
- 1、搜索时,搜索关键字默认为search
- 2、搜索的值,不需要加引号,如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 filtersclass 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 。
如下,设置支持id 、name、leader的排序
# 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 _PageNumberPaginationclass 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 = 50invalid_page_message = '无效页码'
1、通过继承的方式,重写PageNumberPagination
2、我们自定义的类,名称也想叫做 PageNumberPagination 。解决办法:先引入父类PageNumberPagination,然后再给他取一个别名。
from rest_framework.pagination import PageNumberPagination as _PageNumberPaginationclass 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 = ProjectModelSerializerfilter_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 project的settings中:
REST_FRAMEWORK = {'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']}
或者你也可以将filter backend添加到一个单独的view或viewSet中:
from django_filters.rest_framework import DjangoFilterBackendclass UserListView(generics.ListAPIView):...filter_backends = [DjangoFilterBackend]
如果只需要简单的根据是否相等的过滤,则可以在视图或视图集上设置filterset_fields
属性,列出要过滤的字段集合。
class ProductList(generics.ListAPIView):queryset = Product.objects.all()serializer_class = ProductSerializerfilter_backends = [DjangoFilterBackend]filterset_fields = ['category', 'in_stock']
这将自动为给定的字段创建一个FilterSet
类,并允许你发出如下请求:
http://example.com/api/products?category=clothing&in_stock=True
对于更高级的过滤要求,你可以指定视图应使用的FilterSet
类。你可以在django-filter文档中阅读有关FilterSets的更多信息。还建议你阅读有关DRF集成的部分。