2016-07-10 21 views
0

Ich arbeite an einem Django-Projekt, in dem ich versuche, alle Produkte mit update_ts Feld größer als product_sync_ts von Product Tabelle vom Server zu einer Zeit, aber da die Anzahl der Produkte ist groß erfordert eine große Menge an Zeit, um alle Daten abzurufen. Ich gebe auch den aktuellen Zeitstempel zusammen mit den Daten zurück. Nun möchte ich die Ergebnisse paginieren.mit Paginierung in Serializer Django

Mein vorheriger Code:

Views.py

@api_view(['GET']) 
def productlist(request, format=None): 
    product_sync_ts = request.GET.get(
      'product_sync_ts', None) 
    if product_sync_ts: 
     product =Product.objects.filter(
      update_ts__gt=product_sync_ts) 
     ) 
     serializer = SyncedProductSerializer(
      instance={'products': product}) 
     return response(serializer.data) 
    else: 
     content = {'details': "Bad Request"} 
     raise APIException400(request, content) 

serializer.py

class SyncedProductSerializer(serializers.Serializer): 
    product_sync_ts = serializers.SerializerMethodField(
     method_name='get_current_ts' 
    ) 
    products = ProductSerializer(many=True, read_only=True) 

    class Meta: 
     fields = ('products', 'product_sync_ts') 

    def get_current_ts(self, obj): 
     product_sync_ts = datetime.utcnow().isoformat(' ') 
     return product_sync_ts 




class ProductSerializer(serializers.ModelSerializer): 
    image_url = serializers.SerializerMethodField(
     method_name='change_image_url' 
    ) 

    class Meta: 
     model = Product 
     fields = (
      'id', 
      'name', 
      'unit', 
      'price', 
      'image_url' 
     ) 

    def change_image_url(self, obj): 
     return ''.join([ 
      CDN_URL, str(obj.image_url) 
     ]) if str(obj.image_url) else None 

Wie ich versuchte, es für Paginierung ändern:

Views.py

class PaginatedProductList(APIView): 

    def get(self, request, format=None): 
     product_sync_ts = request.GET.get(
      'product_sync_ts', None) 
     if product_sync_ts: 
      product = GrProduct.objects.filter(
       update_ts__gt=product_sync_ts 
      ) 
      paginator = Paginator(product, 1000) 
      page = request.GET.get('page') 
      try: 
       product = paginator.page(page) 
      except PageNotAnInteger: 
       product = paginator.page(1) 
      except EmptyPage: 
       product = paginator.page(paginator.num_pages) 

      serializer = SyncedProductSerializer(
       instance={'products': product}) 
      return Response(serializer.data) 
     else: 
      content = {'details': "Bad Request"} 
      raise APIException400(request, content) 

Das funktioniert gut, ich paginierte Ergebnisse bin immer, aber das Problem ist, dass ich nicht in der Lage bin die nächste und vorherige Seite Informationen an den Client zu senden. Der Client hat keine Möglichkeit zu wissen, wie viele Seiten gültig sind (nicht leer).

Kann mir jemand vorschlagen, wie ich meinen Code ändern kann, um dies zu tun.

Antwort

2

Hier ist ein Beispiel, wie die Ergebnisse mit einer APIView Klasse und PageNumberPagination Paginierung Paginieren Klasse:

from rest_framework.views import APIView 
from rest_framework.pagination import PageNumberPagination 

class ProductList(APIView, PageNumberPagination): 
    # number of items per page by default 
    page_size = 1000 
    # max number of items per page 
    max_page_size = 1000 

    def get_queryset(self): 
     product_sync_ts = self.request.GET.get('product_sync_ts', None) 
     if product_sync_ts: 
      products = GrProduct.objects.filter(update_ts__gt=product_sync_ts) 
      return self.paginate_queryset(products, self.request) 

     raise APIException400(request, {'details': "Bad Request"}) 

    def get(self, request): 
     products = self.get_queryset() 
     serializer = SyncedProductSerializer(instance={'products': products}) 
     return self.get_paginated_response(serializer.data) 

liest DRF - PageNumberPagination Ihre Paginierung

+0

Danke, es funktionierte wie ein Charme :) –

+0

Auch wie kann ich page_size und current_page_number zusammen mit next hinzufügen und vorher? –

+0

Ich wollte die get_paginated_response-Methode anpassen, aber ich bin mir nicht sicher, ob ich es richtig mache oder nicht –

2

Es gibt GenericAPIView die get_paginated_response Methode hat die

return self.paginator.get_paginated_response(data) 

kehrt So brauchen Sie nur diese Mixin Unterklasse

from rest_framework.generics import GenericAPIView 

class PaginatedProductList(GenericAPIView): # Fixed 

    def get(self, request, format=None): 
     product_sync_ts = request.GET.get(
      'product_sync_ts', None) 
     if product_sync_ts: 
      product = GrProduct.objects.filter(
       update_ts__gt=product_sync_ts 
      ) 
      paginator = Paginator(product, 1000) 
      page = request.GET.get('page') 
      try: 
       product = paginator.page(page) 
      except PageNotAnInteger: 
       product = paginator.page(1) 
      except EmptyPage: 
       product = paginator.page(paginator.num_pages) 

      serializer = SyncedProductSerializer(
       instance={'products': product}) 
      return paginator.get_paginated_response(serializer.data) # <- here it is 
     else: 
      content = {'details': "Bad Request"} 
      raise APIException400(request, content) 
+0

konfiguriert Es sagt 'Attribut:‚PaginatedProductList‘Objekt hat kein Attribut‚get_paginated_response'' –

+0

Leider müssen Sie Unterklasse 'GenericAPIView' –

+0

Feste noch working..I den gleichen Fehler ist nicht immer: ( –