上一章:
六、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 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 。
如下,设置支持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 _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 project的settings中:
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
或者你也可以将filter backend添加到一个单独的view或viewSet中:
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 方法实现。文章来源:https://www.toymoban.com/news/detail-474230.html
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://www.toymoban.com/news/detail-474230.html
到了这里,关于七、Django DRF框架GenericAPIView--搜索&排序&分页&返回值的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!