排序与分页

有时,客户端希望 RESTful Web API 提供经过排序后的字段,比如,按照年龄从大到小排列学生;有时,根据客户端条件,需要返回给前端的数据过多,如果一次提供,会大大降低响应速度。此时,可将数据做分割,分成不同的小份,发送给客户端。这一节,我们为大家介绍 RESTful Web API 如何实现数据的排序与分页。

1.排序的使用

在类视图中设置 filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework 会在请求的查询字符串参数中检查是否包含了 ordering 参数,如果包含了 ordering 参数,则按照 ordering 参数指明的排序字段对数据集进行排序。

前端可以传递的 ordering 参数的可选字段值需要在 ordering_fields 中指明。

示例:

class StudentViewSet(ModelViewSet):
    queryset = StudentsModel.objects.all()
    serializer_class = StudentsSerializer
    filter_backends = [OrderingFilter]
    ordering_fields = ('id', 's_age', 's_number')

此时,访问 http://127.0.0.1:8000/api/students/?ordering=-s_age ,服务器返回按年龄逆序排序后的学生信息。

2.分页的使用

REST framework 提供了分页的支持。

有时,前端根据一定的条件查询的数据量是惊人的,如果按照查询条件,一次性返回所有数据,往往会使服务器承受巨大的压力,此时我们可以以分页的方式提供数据,相当于将庞大的数据打散,每次只按要求返回一定数量的数据,就可以减轻服务器压力。在 Django Rest framework 中,可以在配置文件中设置全局的分页方式,如:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 100  # 每页返回的数据条数
}

也可通过自定义 Pagination 类,来为视图添加不同分页行为。在视图中通过pagination_clas 属性来指明。

class LargeResultsSetPagination(PageNumberPagination):
    page_size = 1000
    page_size_query_param = 'page_size'
    max_page_size = 10000
class StudentViewSet(ModelViewSet):
    queryset = StudentsModel.objects.all()
    serializer_class = StudentsSerializer
    pagination_class = LargeResultsSetPagination

注意:如果需要关闭分页功能,只需在视图内设置

pagination_class = None

3.自定义分页器

如果默认的分页功能无法满足要求,可以自行定义分页器。

3.1 PageNumberPagination

前端访问网址形式:

GET  http://127.0.0.1/api/students/?page=4

可以在子类中定义的属性:

  • 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_query_param = 'page_size' # 每页数据条数
    max_page_size = 10

class StudentViewSet(ModelViewSet):
    queryset = StudentsModel.objects.all()
    serializer_class = StudentsSerializer
    pagination_class = StandardPageNumberPagination

3.2 LimitOffsetPagination

前端访问网址形式:

GET http://127.0.0.1/api/students/?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 StudentViewSet(ModelViewSet):
    queryset = StudentsModel.objects.all()
    serializer_class = StudentsSerializer
    pagination_class = LimitOffsetPagination

4.小结

本小节介绍了排序和分页功能,这两个功能也是开发中使用频率较高的功能,排序功能可以按一定顺序返回数据,而分页功能可以减轻服务器压力,节省客户端得到响应的时间。在使用分页时,要注意 offset(偏移量)参数,很多返回的数据与理想数据不一致,通常都是该参数出现了问题。大家要理解核心原理,这样才能在使用时得心应手。