私は非常に単純な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
_
このテーマについて 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)
別のオプションは、ページネーションクラスから継承することで、ビュークラスの変更が少なくなります。
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)
ページネーションを行う別の方法は、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