一、过滤Filtering
对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。
pip install django-filter
在配置文件中增加过滤后端的设置:
INSTALLED_APPS = [
...
'django_filters', # 需要注册应用,
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
在视图中添加filter_fields属性,指定可以过滤的字段
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
filter_fields = ('btitle', 'bread')
# 127.0.0.1:8000/books/?btitle=西游记
然后访问127.0.0.1:8000/books/?btitle=西游记
二、排序
对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。
使用方法:
-
在类视图中设置
filter_backends
,使用rest_framework.filters.OrderingFilter
过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。 -
前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。
示例:
from rest_framework.filters import OrderingFilter
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
#指定过滤后端为排序
filter_backends = [OrderingFilter]
#指定排序字段
ordering_fields = ('id', 'bread', 'bpub_date')
# http://127.0.0.1:8000/books/?ordering=-id
访问http://127.0.0.1:8000/books/?ordering=-id,以id从大到小排序
三、分页Pagination
REST framework提供了分页的支持。
1、我们可以在配置文件中设置全局的分页方式
如:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 2 # 每页数目
}
设置了上面两行后访问/books,可以看到返回的数据格式也发生了改变,count为总数量,results里为分页后返回的数据,这里只有两个数据
注意:全局的方式不支持指定每页个数,所以还需要下面的自定义分页器
2、也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_clas属性来指明。
from rest_framework.pagination import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
page_size = 2
page_size_query_param = 'page_size'
max_page_size = 100
注意:如果在视图内关闭分页功能,只需在视图内设置
pagination_class = None
可选分页器
1) PageNumberPagination
前端访问网址形式:
GET http://api.example.org/books/?page=4&page_size=2
可以在子类中定义的属性:
page_size 每页数目
page_query_param 前端发送的页数关键字名,默认为"page"
page_size_query_param 前端发送的每页数目关键字名,默认为None
max_page_size 前端最多能设置的每页数量
from rest_framework.pagination import PageNumberPagination
class StandardPageNumberPagination(PageNumberPagination):
page_size = 2
page_query_param = 'page'
page_size_query_param = 'page_size'
max_page_size = 10
class BookListView(ListAPIView):
queryset = BookInfo.objects.all().order_by('id')
serializer_class = BookInfoSerializer
#指定自定义分页器
pagination_class = StandardPageNumberPagination
# 127.0.0.1/books/?page=2&page_size=2
访问第二页,每页格式为2 http://127.0.0.1:8000/books/?page=2&page_size=2
2)LimitOffsetPagination
前端访问网址形式:
GET http://api.example.org/books/?limit=100&offset=400
可以在子类中定义的属性:
default_limit 默认限制,默认值与PAGE_SIZE设置一直
limit_query_param limit参数名,默认'limit'
offset_query_param offset参数名,默认'offset'
max_limit 最大limit限制,默认None
from rest_framework.pagination import LimitOffsetPagination
class BookListView(ListAPIView):
queryset = BookInfo.objects.all().order_by('id')
serializer_class = BookInfoSerializer
pagination_class = LimitOffsetPagination
# 127.0.0.1:8000/books/?offset=3&limit=2
3、在自定义APIView的get方法中使用分页器
参考 rest_framework 分页器组件
上面的示例中直接指定pagination_class来使用分页器,因为drf帮我们把get视图方法已经写好了,我们只需要指定分页器。但如果有时候drf的方法不能满足我们的需求,我们需要自己来定义视图方法的时候,就需要自己调用分页器了。
示例
class BookListAPIView(APIView):
"""列表视图"""
def get(self, request):
"""查询所有"""
queryset = BookInfo.objects.all()
pagePagination = PageNumberPagination() # 产生一个分页器对象
pagePagination.page_query_param = 'page' # 前台查询第几页的参数,一般不需要改,系统默认查询参数为 page
pagePagination.page_size_query_param='page_size' #前端发送的每页数目关键字名,默认为None
pagePagination.max_page_size = 100 # 后台控制显示的最大记录条数,防止前台输入的查询条数过大
ret = pagePagination.paginate_queryset(queryset, request) # 必须传两个参数,第一个queryset对象要分页的所有数量,第二个参数request
serializer = BookInfoModelSerializer(instance=ret, many=True)
return Response(serializer.data)
可以使用自定义分页器,将一些参数在自定义分页器中设置好,省得每次都有重复设置。
class StandardPageNumberPagination(PageNumberPagination):
page_size = 2
page_query_param = 'page'
page_size_query_param = 'page_size'
max_page_size = 100
class BookListAPIView(APIView):
"""列表视图"""
def get(self, request):
"""查询所有"""
qs = BookInfo.objects.all()
pagePagination = StandardPageNumberPagination() # 产生一个自定义分页器对象,下面注释部分在自定义分页器中已经设置了
#pagePagination.page_query_param = 'page' # 前台查询第几页的参数,一般不需要改,系统默认查询参数为 page
#pagePagination.page_size_query_param='page_size' #前端发送的每页数目关键字名,默认为None
#pagePagination.max_page_size = 100 # 后台控制显示的最大记录条数,防止前台输入的查询条数过大
pagedata = pagePagination.paginate_queryset(qs, request) # 必须传两个参数,第一个queryset对象要分页的所有数量,第二个参数request
serializer = BookInfoModelSerializer(instance=pagedata, many=True) #对数据进行序列化
pageresponse = pagePagination.get_paginated_response(serializer.data) # 将序列化后的数据再转为分页格式的输出,有带count等参数,如果没有这一步,则还是默认的输出方式
return Response(pageresponse.data)
路由
re_path(r'^books/$', views.BookListAPIView.as_view())
访问正常http://127.0.0.1:8000/books/?page=2&page_size=3