webentwicklung-frage-antwort-db.com.de

Django Rest Framework: Paginierung in einem ViewSet aktivieren (wie ModelViewSet Paginierung)

Ich habe ein ViewSet wie dieses, um die Benutzerdaten aufzulisten:

class Foo(viewsets.ViewSet):

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

Ich möchte die Paginierung wie die Standardpaginierung für ModelViewSet aktivieren:

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

Das offizielle Dokument sagt:

Die Paginierung wird nur automatisch durchgeführt, wenn Sie die allgemeinen Ansichten oder Ansichten-Sets verwenden

... aber mein Resultset ist überhaupt nicht paginiert. Wie kann ich es paginieren?

30
floatingpurr

Die Paginierung wird nur automatisch durchgeführt, wenn Sie die allgemeinen Ansichten oder Ansichten-Sets verwenden

Die erste Straßensperre ist die Übersetzung der Dokumente ins Englische. Was sie vermitteln wollten, ist, dass Sie ein generisches Viewset wünschen. Die generischen Viewsets reichen von generische ApiViews , die über zusätzliche Klassenmethoden zum Paginieren von Abfragesets und Antworten verfügen.

Darüber hinaus stellen Sie Ihre eigene list -Methode bereit, aber der Standard-Paginierungsprozess wird tatsächlich von mixin ausgeführt:

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)

Die einfache Lösung, verwenden Sie den Framework-Code:

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

Die komplexere Lösung wäre, wenn Sie eine benutzerdefinierte list -Methode benötigen, die Sie nach Belieben schreiben sollten, jedoch im Stil des obigen Mixin-Code-Snippets.

35
Mark Galloway

Für diejenigen, die DRF 3.1 oder höher verwenden, wird die Standardmethode für die Paginierung geändert. Siehe http://www.Django-rest-framework.org/topics/3.1-announcement/ für Details.

Wenn Sie nun die Paginierung für ein ModelViewSet aktivieren möchten, können Sie dies entweder global tun, indem Sie Folgendes in Ihrer settings.py-Datei festlegen:

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

Oder wenn Sie es nur für ein ModelViewSet möchten, können Sie die Paginierungsklasse für nur dieses Viewset manuell festlegen.

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

Auf diese Weise können Sie auch die Art und Weise anpassen, wie die Paginierung nur für dieses Viewset behandelt wird.

DRF 3.1 hat auch neue Arten von Standard-Paginierungsschemata eingeführt, die Sie verwenden können, z. B. LimitOffset und Cursor.

28
jeffjv

Versuchen Sie, eine Klassenvariable bereitzustellen

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

Erstellen Sie ein benutzerdefiniertes ViewSet, das derzeit nur die list Operation ausführt, wie Sie es hier tun.

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

Erben Sie nun Ihre Klasse Foo mit diesem benutzerdefinierten Ansichten-Set

class Foo(ListModelViewSet):

    paginate_by = 10

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

Dies sollte Ihnen helfen, die Paginierung zum Laufen zu bringen.

3
Arpit Goyal

Paginierung in DRF unter Verwendung von Viewsets und Listen

Hier habe ich eine Ausnahme behandelt. Wenn die Seite leer ist, werden leere Datensätze angezeigt

Bei der Festlegung der Seitengröße ist diese Seitengröße global und wird von paginator_queryset in view verwendet

REST_FRAMEWORK = {'PAGE_SIZE': 10,}

In der Ansicht von rest_framework werden Mixins und Viewsets importiert

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
        })

**> Hinweis: Wenn Sie Order_by nicht verwenden, wird aufgrund dieser Liste eine Ausnahme angezeigt

gibt ungeordnete Liste. **

2
Vinay Kumar

Eine etwas einfachere Variante von diese Antwort , wenn Sie eine Paginierung für ein bestimmtes ViewSet wünschen, aber die Seitengröße nicht anpassen müssen:

REST_FRAMEWORK = {
    'PAGE_SIZE': 100
}

class FooViewSet(viewsets.ModelViewSet):
    pagination_class = PageNumberPagination
1
morningstar