Django RestFramework: 在 ViewSet 上打开分页(如 ModelViewSet 分页)

我有一个类似的 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": [{...},{...},...,{...}]
}

官方文件说:

只有在使用通用视图或视图集时,才会自动执行分页

... 但是我的结果集根本没有分页。我怎样才能分页呢?

76982 次浏览

尝试提供一个类变量

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)

这应该可以帮助您使分页正常工作。

分页只有在使用泛型时才自动执行 视图或视图集

第一个障碍是把文件翻译成英文。他们想要传达的是您需要一个通用视图集。泛型视图集从 通用视图扩展而来,通用视图具有用于分页查询集和响应的额外类方法。

此外,您还提供了自己的 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)

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

class Foo(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = User.objects.all()
serializer = UserSerializer

更复杂的解决方案是,如果您需要一个自定义 list方法,那么您应该按照您认为合适的方式编写它,但使用上面的 Mixin 代码片段的样式。

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

现在,如果你想为一个 ModelViewSet 启用分页,你可以在 setings.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。

使用 viewsetslistDRF中分页。

这里我处理了一个异常,如果 呼叫空荡荡的它将显示 空荡荡的记录。

在设置定义页面大小时,该页面大小为 全球性的,并由视图中的 paginator_queryset使用。

REST _ FRAMEWORK = {‘ PAGE _ SIZE’: 10,}

View.py:

from 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_200_OK,
"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,它将显示 exception,因为这个列表 给出无序列表。

如果你想对特定的 ViewSet进行分页,但是不需要自定义页面大小,那么 这个答案的一个稍微简单一些的变体是:

REST_FRAMEWORK = {
'PAGE_SIZE': 100
}


class FooViewSet(viewsets.ModelViewSet):
pagination_class = PageNumberPagination

这种方法也适用于 Django Rest apiViewsApi’s

from rest_framework.pagination import PageNumberPagination
class FooList(APIView):


page_size = 10


def get(self, request):
foo = Foo.objects.all()
paginator = PageNumberPagination()
paginator.page_size = page_size
result_page = paginator.paginate_queryset(foo, request)
serializer = FooSerializer(result_page, many=True)
return paginator.get_paginated_response(serializer.data)

使用 GenericAPIView 自定义分页
1.view.py 文件 < br >

class ModelView(GenericAPIView):
pagination_class = CustomPagination
def post(self, request):
data = request.data
example_data = data.get('comment_id')
replies = ExampleModel.objects.filter(model_field=example_data).order_by('-id')
if replies.exists():
replies = self.paginate_queryset(replies)
replies = self.get_paginated_response(replies)
return replies
else:
return Response({'message': 'This is the reply message!'}, status=status.HTTP_200_OK)

Py 文件

class CustomPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 1000
def get_paginated_response(self, data):
return Response({
'links': {
'next': self.page.next_page_number() if self.page.has_next() else None,
'previous': self.page.previous_page_number() if self.page.has_previous() else None
},
'total': self.page.paginator.count,
'page': int(self.request.GET.get('page', 1)),
'page_size': int(self.request.GET.get('page_size', self.page_size)),
'results': ModelSerializer(data, context={'request':self.request}, many=True).data
}, status=status.HTTP_200_OK)

3.my _ Series alizer.py 文件

class ModelSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
def to_representation(self, instance):
ret = super().to_representation(instance)
request = self.context.get('request')
if instance.user_information.image else None
ret['user_name'] = instance.user_information.name
 

return ret

这就是你所需要的。