Python中Django Rest Framework如何在ModelViewSet中同时实现分页和获取所有数据

RT,求大神指教,🙏
Python中Django Rest Framework如何在ModelViewSet中同时实现分页和获取所有数据

3 回复

在DRF的ModelViewSet里,要同时支持分页和获取所有数据,最直接的办法是自定义一个视图集,根据请求参数动态切换分页行为。下面是一个完整的实现示例:

from rest_framework import viewsets, pagination
from rest_framework.response import Response
from rest_framework.decorators import action
from django.core.paginator import Paginator, EmptyPage
from .models import YourModel
from .serializers import YourModelSerializer

class YourModelViewSet(viewsets.ModelViewSet):
    queryset = YourModel.objects.all()
    serializer_class = YourModelSerializer
    pagination_class = pagination.PageNumberPagination
    
    def list(self, request, *args, **kwargs):
        # 检查请求参数中是否有'all'参数
        get_all = request.query_params.get('all', '').lower() == 'true'
        
        if get_all:
            # 禁用分页,返回所有数据
            self.paginator = None
            queryset = self.filter_queryset(self.get_queryset())
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
        else:
            # 使用默认的分页逻辑
            return super().list(request, *args, **kwargs)

这样配置后,你可以通过不同的URL参数来控制分页:

  • 正常分页:/api/yourmodel/
  • 获取所有数据:/api/yourmodel/?all=true

如果你想要更灵活的控制,还可以添加一个自定义的action:

class YourModelViewSet(viewsets.ModelViewSet):
    # ... 其他代码同上 ...
    
    @action(detail=False, methods=['get'])
    def all(self, request):
        """获取所有数据的专用端点"""
        queryset = self.filter_queryset(self.get_queryset())
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

这样就有了两个端点:

  • /api/yourmodel/ - 分页数据
  • /api/yourmodel/all/ - 所有数据

两种方式都能很好地解决你的需求,第一种更简洁,第二种更符合RESTful风格。根据你的具体场景选择即可。

总结:通过动态控制分页器或添加专用action来实现分页和全数据的切换。


你可以这样实现
from django.shortcuts import render
from django.contrib.auth.models import User
import random
from rest_framework.response import Response
# Create your views here.
b = [str(i) for i in range(10)]
for i in range(10):
a = random.sample(b, 5)
User.objects.update_or_create(username=’’.join(a))


from rest_framework import serializers
from rest_framework import pagination
from rest_framework.viewsets import ModelViewSet
from collections import OrderedDict, namedtuple


class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = 'all


class UserPagination(pagination.PageNumberPagination):
page_size = 20

def get_paginated_response(self, data):
return Response(OrderedDict([
(‘count’, self.page.paginator.count),
(‘next’, self.get_next_link()),
(‘previous’, self.get_previous_link()),
(‘page_size’, self.page_size),
(‘results’, data)
]))


class UserViewset(ModelViewSet):
serializer_class = UserSerializer
pagination_class = UserPagination

def get_queryset(self):
return User.objects.all()

def list(self, request, *args, **kwargs):

status = request.query_params.get(“status”)
users = self.get_queryset()
if status == ‘1’:
self.paginator.page_size = users.count()

page = self.paginate_queryset(users)
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)


效果如下


回到顶部