问题
I am working on a django project in which I am trying to fetch all the products having update_ts
field greater than product_sync_ts
from Product
table from the server at a time, but since the number of products is large this requires a large amount of time to fetch all data.I am also returning the current time stamp along with the data.Now I want to paginate the results.
My Previous 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
How I tried modifying it for pagination :
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)
This is working fine, I am getting paginated results,but the problem is that I'm not able to send the next and previous page information to the client. The client has no way to know what are the valid(non-empty) number of pages.
Can someone suggest me how can I modify my code in order to do so.
回答1:
Here is an example how to paginate results with an APIView
class and PageNumberPagination
pagination class :
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)
Read DRF - PageNumberPagination to configure your pagination
回答2:
There is GenericAPIView which has get_paginated_response
method which returns
return self.paginator.get_paginated_response(data)
So you just need to subclass this Mixin
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)
来源:https://stackoverflow.com/questions/38290029/using-pagination-in-serializer-django