web-dev-qa-db-ja.com

Django Rest Framework-APIViewページネーション

私は非常に単純なAPIViewを持っていますが、ここではページネーションの設定方法がわかりません。このシナリオでは、与えられたEventを使用してpkを選択し、このNewsItemsに割り当てられているすべてのEventを取得します。

ListCreateAPIViewでクエリセットを最初に定義すると、_pagination_class = LimitOffsetPagination_は問題なく動作します。 queryset = Event.objects.all()ですが、カスタムgetではありません:

_class EventNewsItems(APIView):
    pagination_class = LimitOffsetPagination

    def get(self, request, pk, format=None):

        #user = request.user
        event = Event.objects.get(pk=pk)
        news = event.get_news_items().all()

        serializer = NewsItemSerializer(news, many=True, context={'request':request})
        response = Response(serializer.data, status=status.HTTP_200_OK)
        return response
_

解決済み:

_def get(self, request, pk, format=None):

    #user = request.user
    event = Event.objects.get(pk=pk)
    news = event.get_news_items().all()
    paginator = LimitOffsetPagination()
    result_page = paginator.paginate_queryset(news, request)
    serializer = NewsItemSerializer(result_page, many=True, context={'request':request})
    response = Response(serializer.data, status=status.HTTP_200_OK)
    return response
_
18
user3128673

このテーマについて Q&Aスタイルの例 を作成しました。
ソートの要約として:

Django Rest Frameworksのソースコードとそれらがページネーションを処理する方法を利用することにより、ビュークラス内に同じメソッドを作成し、ソリューションがデフォルトのメソッドを使用するのと同じ方法でそれらを使用します。

上記のドキュメントから引用:

from rest_framework.settings import api_settings
from rest_framework.views import APIView

class MyView(APIView):
    queryset = OurModel.objects.all()
    serializer_class = OurModelSerializer
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS # cool trick right? :)

    # We need to override get method to achieve pagination
    def get(self, request):
        ...
        page = self.paginate_queryset(self.queryset)
        if page is not None:
            serializer = self.serializer_class(page, many=True)
            return self.get_paginated_response(serializer.data)

        ... Do other stuff needed (out of scope of pagination)

    # Now add the pagination handlers taken from 
    #  Django-rest-framework/rest_framework/generics.py

    @property
    def paginator(self):
        """
        The paginator instance associated with the view, or `None`.
        """
        if not hasattr(self, '_paginator'):
            if self.pagination_class is None:
                self._paginator = None
            else:
                self._paginator = self.pagination_class()
        return self._paginator

     def paginate_queryset(self, queryset):
         """
         Return a single page of results, or `None` if pagination is disabled.
         """
         if self.paginator is None:
             return None
         return self.paginator.paginate_queryset(queryset, self.request, view=self)

     def get_paginated_response(self, data):
         """
         Return a paginated style `Response` object for the given output data.
         """
         assert self.paginator is not None
         return self.paginator.get_paginated_response(data) 
12
John Moutafis

別のオプションは、ページネーションクラスから継承することで、ビュークラスの変更が少なくなります。


class EventNewsItems(APIView, LimitOffsetPagination):

    def get(self, request, pk, format=None):
        event = Event.objects.get(pk=pk)
        news = event.get_news_items().all()

        results = self.paginate_queryset(news, request, view=self)
        serializer = NewsItemSerializer(results, many=True)
        return self.get_paginated_response(serializer.data)
4
giantas

ページネーションを行う別の方法は、Paginatorクラスを使用することです。

回答クエリに加えて、表示するページ数とページが持つ要素の範囲を設定する必要があります。

ページ番号とアイテムの範囲は、リクエストパラメータの一部として、または選択した方法で提供できます。

質問のケースを例にとると:

from Django.core.paginator import Paginator

class EventNewsItems(APIView):

    def get(self, request, pk, format=None):

        #user = request.user
        event = Event.objects.get(pk=pk)
        news = event.get_news_items().all()

         # -----------------------------------------------------------
        page_number = self.request.query_params.get('page_number ', 1)
        page_size = self.request.query_params.get('page_size ', 10)

        paginator = Paginator(news , page_size)
        serializer = NewsItemSerializer(paginator.page(page_number) , many=True, context={'request':request})
        # -----------------------------------------------------------

        response = Response(serializer.data, status=status.HTTP_200_OK)
        return response
0
Peter Paul