如何使用paginator类对视图集进行分页?

时间:2017-10-24 16:59:47

标签: django django-rest-framework

根据文件:

Pagination is only performed automatically if you're using the generic views or viewsets

但事实并非如此。这就是我对我的观点的看法:

views.py
class EntityViewSet(viewsets.ViewSet):
    def list(self, request):
        queryset = Entity.objects.all()
        serializer = EntitySerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        queryset = Entity.objects.all()
        entity = get_object_or_404(queryset, pk=pk)
        serializer = EntitySerializer(entity)
        return Response(serializer.data)

这是我的网址

entity_list = views.EntityViewSet.as_view({'get':'list'})
entity_detail = views.EntityViewSet.as_view({'get':'retrieve'})
    ...
    url(r'^entity/$', entity_list, name='entity-list'),
    url(r'^entity/(?P<pk>[0-9]+)/$', entity_detail, name='entity-detail'),
    ...

这是我的分页课

class PagePaginationWithTotalPages(pagination.PageNumberPagination):
    page_size = 30
    page_size_query_param = 'page_size'
    max_page_size = 1000

    def get_paginated_response(self, data):
        return Response({
            'next': self.get_next_link(),
            'previous': self.get_previous_link(),
            'count': self.page.paginator.count,
            'total_pages': self.page.paginator.num_pages,
            'results': data
        })

我将它设置在settings.py

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated'
    ],
    'DEFAULT_PAGINATION_CLASS': 'myapp.pagination.PagePaginationWithTotalPages',
    'UNICODE_JSON': False,
}

现在虽然这适用于ListAPIView,但它似乎不适用于我的视图集。我有一个缺失的步骤吗?

作为参考,这很好用:

class EntitiesView(ListAPIView):
    serializer_class = EntitySerializer

    def get_queryset(self):
        parameters = get_request_params(self.request)
        qs = qs.filter(**parameters).distinct()
        return qs

编辑:

更改它以使用ModelViewset似乎已经完成了这个技巧

class EntityViewSet(viewsets.ModelViewSet):
    queryset = Entity.objects.all()
    serializer_class = EntitySerializer

    def list(self, request):
        queryset = self.queryset
        parameters = get_request_params(self.request)
        if 'ordering' in parameters:
            queryset = queryset.order_by(parameters['ordering'])
            del parameters['ordering']
        queryset = queryset.filter(**parameters).distinct()

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        entity = self.get_object()
        serializer = EntitySerializer(entity)
        return Response(serializer.data)

1 个答案:

答案 0 :(得分:1)

  

只有在使用通用视图或视图集

时才会自动执行分页

您似乎错过了文档中的下一句话:

  

如果您使用常规APIView,则需要自己调用分页API以确保返回分页响应。有关示例,请参阅mixins.ListModelMixin和generics.GenericAPIView类的源代码。

正如文档所指出的,ListModelMixin会告诉您没有调用paginate_queryset / get_paginated_response,从而绕过了分页和过滤。

正如评论中所指出的,您应该考虑ModelViewSet并定义所需的queryset以自动包含它。