在序列化程序django中使用分页

时间:2016-07-10 08:23:14

标签: django pagination django-rest-framework serializer

我正在开发一个django项目,我试图从服务器一次从git merge --no-commit B git checkout A -- stuff to not/delete git commit 表中获取update_ts字段大于product_sync_ts的所有产品,但是产品数量很大,这需要大量的时间来获取所有数据。我还返回当前时间戳和数据。现在我想分页结果。

我以前的代码:

Views.py

Product

serializer.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)

我是如何尝试修改分页的:

Views.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

这很好用,我得到分页结果,但问题是我无法将下一页和上一页信息发送给客户端。客户端无法知道有效(非空)页数是多少。

有人可以建议我如何修改我的代码才能这样做。

2 个答案:

答案 0 :(得分:3)

以下是如何使用APIView类和PageNumberPagination分页类对结果进行分页的示例:

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)

阅读DRF - PageNumberPagination以配置您的分页

答案 1 :(得分:2)

GenericAPIViewget_paginated_response方法返回

return self.paginator.get_paginated_response(data)

所以你只需要继承这个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)