J'ai actuellement une configuration de vue API comme suit:
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)
Ici CartDetailSerializer
est un ModelSerializer normal.
Je veux paginer cette API. Cependant, dans la documentation de DRF, j'ai trouvé ceci:
Si vous utilisez une vue APIView régulière, vous devez appeler vous-même l'API de pagination pour vous assurer de renvoyer une réponse paginée.
Il n'y a pas d'exemple fourni sur la façon de paginer une API APIView standard.
Quelqu'un peut-il poster un exemple que je peux utiliser dans le scénario ci-dessus.
Merci.
Lorsque vous utilisez APIView standard, vous devez utiliser la propre classe Paginator de Django.
La pagination de Django dans Views
Dans votre cas, vous pouvez paginer queryset avant de l'envoyer au sérialiseur.
Quelque chose comme ça:
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)
J'espère que cela t'aides.
Bien que rayy mentionne une possibilité, Django-rest-framework peut gérer cela en interne avec certaines fonctionnalités supplémentaires qui facilitent grandement l'utilisation de votre API. (* notez que la pagination de Django-rest-framework est construite à partir de la pagination Django de Django.core.paginator)
Juste après ce que vous avez cité, vous trouverez les informations clés pour résoudre ce problème:
La pagination est effectuée automatiquement uniquement si vous utilisez les vues ou ensembles de vues génériques. Si vous utilisez une vue APIView régulière, vous devez appeler vous-même l'API de pagination pour vous assurer de renvoyer une réponse paginée. Consultez le code source des classes mixins.ListMixin et generics.GenericAPIView pour obtenir un exemple.
Légère correction à ce qui est indiqué ici: regardez le ListModelMixin.
Si vous allez sur ces deux liens, vous pouvez voir le code source des fichiers ci-dessus: generics.pymixins.py
Ce que vous devez faire, c'est inclure quelque chose comme ceci pour que la pagination fonctionne dans APIView (** remarque: ce code n'a pas été testé, mais l'idée est correcte. Il existe également une meilleure façon de l'écrire plutôt que de l'inclure. à tous points de vue mais je vous laisse le soin de garder ma réponse brève et compréhensible):
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)
J'espère que cela vous a été utile, à vous et aux autres personnes qui ont croisé ce message.
J'utilise DRF version 3.6.2. Vous n'avez pas besoin de beaucoup de code. Utilisez simplement ces étapes simples.
class ProductPagination(PageNumberPagination):
page_size = 5
class product_api(generics.ListCreateAPIView):
queryset = Products.objects.all()
serializer_class = product_serilizer
pagination_class = ProductPagination
si vous voulez une fonctionnalité de recherche par méthode, vous pouvez écrire ci-dessous le code
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
Je préfère prolonger la classe Paginator, voici à quoi cela ressemblerait:
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