現在、次のようにAPIビューを設定しています。
class CartView(APIView):
authentication_classes = [SessionAuthentication, TokenAuthentication]
permission_classes = [IsAuthenticated, ]
api_view = ['GET', 'POST']
def get(self, request, format=None):
try:
cart = request.user.cart
except Cart.DoesNotExist:
cart = Cart.objects.create(user=request.user)
cart_details = cart.cart_details.all()
serializer = CartDetailSerializer(cart_details, many=True, fields=['id', 'item', 'quantity', 'product_type'])
return Response(serializer.data)
ここで、CartDetailSerializer
は通常のModelSerializerです。
このAPIをページ付けしたいと思います。しかし、DRFのドキュメントで、私はこれを見つけました:
通常のAPIViewを使用している場合は、ページ付けされた応答を返すように、自分でページ付けAPIを呼び出す必要があります。
通常のAPIViewAPIをページ付けする方法に関する例は提供されていません。
上記のシナリオで使用できる例を誰かが投稿できますか?.
ありがとう。
通常のAPIViewを使用する場合は、Django独自のPaginatorクラスを使用する必要があります。
あなたの場合、シリアライザーに送信する前にクエリセットをページングすることができます。
このようなもの:
def get(self, request, format=None):
try:
cart = request.user.cart
except Cart.DoesNotExist:
cart = Cart.objects.create(user=request.user)
cart_details = cart.cart_details.all()
paginator = Paginator(cart_details, 10)
page = request.GET.get('page')
try:
cart_details = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
cart_details = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
cart_details = paginator.page(paginator.num_pages)
serializer = CartDetailSerializer(cart_details, many=True, fields=['id', 'item', 'quantity', 'product_type'])
return Response(serializer.data)
お役に立てれば。
Rayyが言及する方法は可能ですが、Django-rest-frameworkは、APIの操作をはるかに簡単にするいくつかの追加機能を使用して、これを内部的に処理できます。 (*注Django-rest-frameworkのページ付けはDjango Django.core.paginatorのpaginatorから構築されます)
引用した直後に、この問題を解決するための重要な情報があります。
ページネーションは、汎用ビューまたはビューセットを使用している場合にのみ自動的に実行されます。通常のAPIViewを使用している場合は、ページ付けされた応答を返すように、自分でページ付けAPIを呼び出す必要があります。 例については、mixins.ListMixinクラスとgenerics.GenericAPIViewクラスのソースコードを参照してください。
そこに記載されている内容を少し修正します。ListModelMixinを見てください。
これらの2つのリンクにアクセスすると、上記のファイルのソースコードを確認できます。 generics.pymixins.py
APIViewでページネーションを機能させるには、次のようなものを含める必要があります(**注:このコードはテストされていませんが、考え方は正しいです。コードを含めるよりも、これを記述するためのより良い方法もあります。すべての見方でですが、私の答えを短く理解できるようにするために、それはあなたに任せます):
from __future__ import absolute_import
# if this is where you store your Django-rest-framework settings
from Django.conf import settings
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Cart
class CartView(APIView):
pagination_class = settings.DEFAULT_PAGINATION_CLASS
def get(self, request, format=None):
#assuming every other field in the model has a default value
cart = Cart.objects.get_or_create(user=request.user)
#for a clear example
cart_details = Cart.objects.all()
page = self.paginate_queryset(cart_details)
if page is not None:
serializer = CartDetailSerializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = CartDetailSerializer(cart_details, many=True)
return Response(serializer.data)
@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)
これがあなたやこの投稿に出くわした他の人たちにもっと役立つことを願っています。
私はPaginatorクラスを拡張することを好みます、これはそれがどのように見えるかです:
from rest_framework import status
from rest_framework.exceptions import NotFound as NotFoundError
from rest_framework.pagination import PageNumberPagination # Any other type works as well
from rest_framework.response import Response
from rest_framework.views import APIView
class CustomPaginator(PageNumberPagination):
page_size = 10 # Number of objects to return in one page
def generate_response(self, query_set, serializer_obj, request):
try:
page_data = self.paginate_queryset(query_set, request)
except NotFoundError:
return Response({"error": "No results found for the requested page"}, status=status.HTTP_400_BAD_REQUEST)
serialized_page = serializer_obj(page_data, many=True)
return self.get_paginated_response(serialized_page.data)
class CartView(APIView):
def get(self, request, format=None):
cart_details = Cart.objects.filter(user=request.user) # or any other query
paginator = CustomPaginator()
response = paginator.generate_response(cart_details, CartDetailSerializer, request)
return response
DRFバージョン3.6.2を使用しています。それほどコーディングする必要はありません。この簡単な手順を使用するだけです。
class ProductPagination(PageNumberPagination):
page_size = 5
class product_api(generics.ListCreateAPIView):
queryset = Products.objects.all()
serializer_class = product_serilizer
pagination_class = ProductPagination
メソッドを取得して検索機能が必要な場合は、以下のコードを記述できます
class ProductPagination(PageNumberPagination):
page_size = 5
class product_api(generics.ListCreateAPIView):
queryset = Products.objects.all()
serializer_class = product_serilizer
pagination_class = SearchProductPagination
def get_queryset(self):
qs = super(product_search_api,self).get_queryset()
searched_product = self.request.query_params.get('searched_product',None)
if search:
qs = Products.objects.filter(Q(product_name__icontains= searched_product))
return qs