Django Rest Framework:在ViewSet上启用分页(如ModelViewSet分页)

时间:2015-08-03 11:24:02

标签: python django django-rest-framework

我有一个像这样的ViewSet来列出用户'数据:

class Foo(viewsets.ViewSet):

    def list(self, request):
        queryset = User.objects.all()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

我想打开分页,就像ModelViewSet的默认分页一样:

{
    "count": 55,
    "next": "http://myUrl/?page=2",
    "previous": null,
    "results": [{...},{...},...,{...}]
}

The official doc说:

  

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

时才会自动执行分页

...但我的结果集根本没有分页。我该如何分页呢?

5 个答案:

答案 0 :(得分:31)

  

只有在您使用通用符号时才会自动执行分页   观点或视图集

第一个障碍是将文档翻译成英文。他们打算传达的是你想要一个通用的视图集。通用视图集从generic ApiViews扩展而来,它具有用于对查询集和响应进行分页的额外类方法。

此外,您提供了自己的add(rNum, ptr); 方法,但默认的分页过程实际上由mixin处理:

fn(rNum, ptr);

简单的解决方案,使用框架代码:

list

如果您需要自定义class ListModelMixin(object): """ List a queryset. """ def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) 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) 方法,那么更复杂的解决方案是,您应该按照您认为合适的方式编写它,但是采用上述mixin代码段的样式。

答案 1 :(得分:27)

对于使用DRF 3.1或更高版本的用户,他们正在更改处理分页的默认方式。有关详细信息,请参阅http://www.django-rest-framework.org/topics/3.1-announcement/

现在,如果要为ModelViewSet启用分页,可以通过设置settings.py文件来全局执行:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 100
}

或者,如果您只想将它​​用于一个ModelViewSet,则可以手动为该视图集设置pagination_class。

from rest_framework.pagination import PageNumberPagination

class StandardResultsSetPagination(PageNumberPagination):
    page_size = 100
    page_size_query_param = 'page_size'
    max_page_size = 1000

class FooViewSet(viewsets.ModelViewSet):
    pagination_class = StandardResultsSetPagination

这也允许您调整仅为该视图集处理分页的方式。

DRF 3.1还引入了可以使用的新类型的默认分页方案,例如LimitOffset和Cursor。

答案 2 :(得分:3)

尝试提供类变量

paginate_by = 10 #This will paginate by 10 results per page.

创建一个自定义ViewSet,目前只执行list操作。

class ListModelViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    pass

现在使用此自定义视图集继承您的类Foo

class Foo(ListModelViewSet):

    paginate_by = 10

    def list(self, request):
        queryset = User.objects.all()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

这可以帮助您实现分页。

答案 3 :(得分:2)

使用视图集和列表

在DRF中进行分页

这里我处理了一个异常如果页面为空,它将显示空记录

在设置定义页面大小时,此页面大小是全局的,并且在视图中由paginator_queryset使用

REST_FRAMEWORK = {' PAGE_SIZE':10,}

在视野中     来自rest_framework import mixins,viewsets

class SittingViewSet(viewsets.GenericViewSet,
    mixins.ListModelMixin):

    serializer_class = SittingSerializer
    queryset = Sitting.objects.all()
    serializer = serializer_class(queryset, many=True)

    def list(self, request, *args, **kwargs):
        queryset =self.filter_queryset(Sitting.objects.all().order_by('id'))

        page = request.GET.get('page')

        try: 
            page = self.paginate_queryset(queryset)
        except Exception as e:
            page = []
            data = page
            return Response({
                "status": status.HTTP_404_NOT_FOUND,
                "message": 'No more record.',
                "data" : data
                })

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

        # serializer = self.get_serializer(queryset, many=True)
        return Response({
            "status": status.HTTP_200_OK,
            "message": 'Sitting records.',
            "data" : data
        })

**指注意:如果您不使用Order_by,它将显示异常,因为此列表

给出无序列表。**

答案 4 :(得分:1)

如果您想对特定的ViewSet进行分页,可以使用this answer上的一个稍微简单的变体,但无需自定义页面大小:

REST_FRAMEWORK = {
    'PAGE_SIZE': 100
}

class FooViewSet(viewsets.ModelViewSet):
    pagination_class = PageNumberPagination