简体   繁体   中英

Pagination based on filtered results in Django Rest Framework

I have a simple filtering in my get function which needs to be paginated. I tried different ways of solving this issue , but I am not able to figure out what exactly needs to be done. The following is my code

class UserInfoViewSets(viewsets.ViewSet):

    def UserInfo_post(self,request, format=None):
        if request.method == 'POST':
            serializer = UserInfoSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def UserInfo_get(self,request,user_token):  
        if request.method == 'GET':
            queryset = UserInfo.objects.filter(user_token=user_token)
            serializer = UserInfoSerializer(queryset,many=True)

I need to paginate the get results. I dont want to write a customized pagination class, but just set the parameter to limit the no of results per page. I have tried setting the following in the setting.py file

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 2,
}

In my views file , I added ListAPIView

class UserInfoListView(generics.ListAPIView):
    model = UserInfo
    serializer_class = UserInfoSerializer
    paginate_by_param = 'limit'

clearly I am overlooking some minor detail. I tried scouting thought the documentation. But it seems to be geared towards people who are well versed with django.

In code below entire viewset is designed GET POST PUT DELETE also your query regarding pagination over filtered query is also handled. Pagination is done using Paginator its a built-in in django

For docs cover most of the part go to django docs for that. DRF docs can be confusing sometimes but django docs are finely descriptive and easy to implement

views.py

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
@api_view(['GET', 'POST'])
def product_list(request):
    if request.method == 'GET':
        products = Product.objects.all()
        product_make_up = Product.objects.filter(item_category__exact='Make Up')[:3]
        product_skincare = Product.objects.filter(item_category__exact='Skin Care')[:3]
        product_fragrance = Product.objects.filter(item_category__exact='Fragrance')[:3]
        product_personal_care = Product.objects.filter(item_category__exact='Personal Care')[:3]
        product_hair_care = Product.objects.filter(item_category__exact='Hair Care')[:3]
        product_item_category = QuerySetChain(product_make_up,
                                          product_skincare,
                                          product_fragrance,
                                          product_personal_care,
                                          product_hair_care)
        item_cates = request.query_params.get('item_category',None)
        if item_cates is not None:
             product = products.filter(item_category=item_cates)
             paginator = Paginator(product,5)
             page = request.query_params.get('page')
             product = paginator.page(page)
             try:
                 product = paginator.page(page)
             except PageNotAnInteger:
                 product = paginator.page(1)
             except EmptyPage:
                 product = pagintor.page(paginator.num_pages)
                 serializer = ProductSerializer(product, many=True)
    else:
        paginator = Paginator(product_item_category,15)
        page = request.query_params.get('page')
        product_item_category = paginator.page(page)
        try:
            product_item_category = paginator.page(page)
        except PageNotAnInteger:
            product_item_category = paginator.page(1)
        except EmptyPage:
            product_item_category = pagintor.page(paginator.num_pages)
        serializer = ProductSerializer(product_item_category, many=True)    
    return Response(serializer.data)
elif request.method == 'POST':
    serializer = ProductSerializer( data=request.data)
    # data.encode("base64")
    if serializer.is_valid():
        serializer.save()
        res_msg = {'Success_Message' : 'Successful','Success_Code' : 200}
        return Response(res_msg)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET', 'PUT', 'DELETE'])
def product_detail(request, pk):
"""
Get, udpate, or delete a specific task
"""
    try:
        product = Product.objects.get(pk=pk)
    except Product.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = ProductSerializer(product)
        return Response(serializer.data , status=status.HTTP_201_CREATED)

    elif request.method == 'PUT':
        serializer = ProductSerializer(product, data=request.data)
        if serializer.is_valid():
            serializer.save()
        return Response(serializer.data)
        else:
            return Response(
            serilizer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        product.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

That is what I do for pagination, filtering, ordering etc... First you need to pip install django-filter ( https://github.com/alex/django-filter )

settings.py

REST_FRAMEWORK = {

    . . . 

    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework.filters.DjangoFilterBackend',
    ),
    'PAGE_SIZE': 1000

    . . .

}

views.py

class UserViewSet(viewsets.ModelViewSet):
    lookup_field = 'id'
    queryset = Users.objects.order_by('id')
    serializer_class = AccountSerializer
    filter_backends = (SearchFilter, OrderingFilter)
    search_fields = ('^id', '^first_name', '^last_name', '^email', ^username',)

I am using AngularJS,

function getUserList(limit, pageNumber, search, ordering) {

    var def = $q.defer();
    offset = (pageNumber -1) * limit;
    $http.get(API_URL +
        '?limit=' +limit +
        '&offset=' + offset +
        '&search=' + search +
        '&ordering=' + ordering)

    .success(function(data){
        def.resolve(data);
    })
    .error(function(data){
        def.resolve(data);
    });

    return def.promise;
}

Example query:

http://127.0.0.1:8000/user/?limit=10&offset=0&search=%20&ordering=id

Thanks @umut and @prashant. I am sharing my version plainly using DRF. Hopefully, others new to drf will find this easier.

def Users_get(self,request,user_token): 
        if request.method == 'GET':
            queryset = Users.objects.filter(user_token=user_token)
            paginator = PageNumberPagination()
            result_page = paginator.paginate_queryset(queryset, request)
            serializer = UsersSerializer(result_page,many=True)
            return paginator.get_paginated_response(serializer.data)

This gave me response with next and previous url links.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM