Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use pagination_class in django-rest-framework for my custom pagination class

My pagination Class

class ArticleListPagination(PageNumberPagination):
    page_size = 2
    page_size_query_param = 'page_size'

My Article View Class

class Article(generics.GenericAPIView):

    queryset = Articles.objects.all()
    serializer_class = ArticlesSerializer
    pagination_class = ArticleListPagination

def get(self, request):
    queryset = self.get_queryset()
    serializer = ArticlesSerializer(queryset, many=True)
    return Response(serializer.data, status=status.HTTP_200_OK)

I am able to use custom pagination class using this

def get(self, request):
    queryset = self.get_queryset()
    page = ArticleListPagination()
    new = page.paginate_queryset(queryset, request)
    serializer = ArticlesSerializer(new, many=True)
    return Response(serializer.data, status=status.HTTP_200_OK)

Is it the proper way to use ArticleListPagination? If I have stated in my class that my pagination class is ArticleListPagination, why it is not changing the return queryset object.

like image 987
Prateek099 Avatar asked Apr 21 '15 10:04

Prateek099


People also ask

How use custom pagination in Django REST framework?

To create a custom pagination class, first create a paginations.py file in your app folder and create a class that inherits from an existing DRF paginator. The parameters given in this custom paginator class will enable you to provide a page_size query parameter to determine the size of each page.

How Pagination works in Django REST framework?

Django provides a few classes that help you manage paginated data – that is, data that's split across several pages, with “Previous/Next” links. REST framework includes support for customizable pagination styles. This allows you to modify how large result sets are split into individual pages of data.

How do I limit pagination in Django?

For pagination in Django models, you need to use limit offset. Suppose you have 20 rows in a queryset and you want to access the data in batches of 5. The syntax is [OFFSET:OFFSET+LIMIT] where offset would be the no. of rows which we want to skip and the limit is the total no.


3 Answers

You can use your custom pagination in viewset and changed on custom view

pagination.py

class OneByOneItems(pagination.PageNumberPagination):
    page_size = 2

    def get_paginated_response(self, data):
        return Response(OrderedDict([
             ('lastPage', self.page.paginator.count),
             ('countItemsOnPage', self.page_size),
             ('current', self.page.number),
             ('next', self.get_next_link()),
             ('previous', self.get_previous_link()),
             ('results', data)
         ]))

views.py

class LectionViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = LectionCourse.objects.all().order_by('-created_at')
    serializer_class = LectionSerializer

    @list_route(methods=['get'], url_path='get-lections/(?P<pk>[^/]+)')
    def get_lection(self, request, pk):
        self.pagination_class = OneByOneItems
        queryset = self.filter_queryset(self.queryset.filter(course=pk))
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)   

serializers.py

class CourseSerializer(serializers.ModelSerializer):
    author = UserCreatorSerializer(many=True)
    project = ProjectSerializer(many=True)

    class Meta:
        model = Course
        fields = ('id', 'theme', 'author', 'project')


class LectionSerializer(serializers.HyperlinkedModelSerializer):
    choose_course = CourseSerializer(source='course')

    class Meta:
        model = LectionCourse
        fields = ('id', 'title', 'video', 'preview_description', 'number', 'choose_course')
like image 82
UserGraund Avatar answered Oct 03 '22 00:10

UserGraund


for django_rest_framework 3.0.x (or below):

You can extends the rest_framework.mixins.ListModelMixin directly, or you imlement the get or list method similar to that.

Of course generics.GenericAPIView is also needed.

def list(self, request, *args, **kwargs):
    queryset = self.filter_queryset(self.get_queryset())
    page = self.paginate_queryset(queryset)
    if page is not None:
        # get_paginaion_serializer will read your DEFAULT_PAGINATION_SERIALIZER_CLASS 
        # or view.pagination_serializer_class 
        # we will talk the two variable later
        serializer = self.get_pagination_serializer(page)
    else:
        serializer = self.get_serializer(queryset, many=True)
    return Response(serializer.data)

if you wanna config it "global", you can config in your settings.py

REST_FRAMEWORK = {
    # ...
    'DEFAULT_PAGINATION_SERIALIZER_CLASS': 'YourCustomPaginationSerializer',
    # ...
}

if you just wanna set to the specific view:

the attribute is pagination_serializer_class instead of pagination_class.

class MyView(generics.GenericAPIView):
    pagination_serializer_class = YourCustomPaginationSerializerClass

for django_rest_framework 3.1.x:

it's a slightly different, you can check the docs first. 3.1 Announcement , Pagination Docs

You can extends the rest_framework.mixins.ListModelMixin directly, or you imlement the get method similar to that.

Of course generics.GenericAPIView is also needed.

def list(self, request, *args, **kwargs):
    queryset = self.filter_queryset(self.get_queryset())

    page = self.paginate_queryset(queryset)
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        return self.get_paginated_response(serializer.data)

    serializer = self.get_serializer(queryset, many=True)
    return Response(serializer.data)

if you wanna config it "global", you can config in your settings.py

REST_FRAMEWORK = {
    # ...
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'

    # ...
}

if you just wanna set to the specific view:

class MyView(generics.GenericAPIView):
    pagination_class = YourCustomPaginationClass
like image 42
soooooot Avatar answered Oct 03 '22 00:10

soooooot


I prefer to use Custom pagination as it will allow you modify your response according to your requirements. This method doesn't require much effort.

Below is my code for this... Hope this will be helpful.

custom_pagination.py

from rest_framework import status
from rest_framework.pagination import LimitOffsetPagination
from rest_framework.response import Response

class CustomPagination(LimitOffsetPagination):
def get_paginated_response(self, data):
    return Response({
        "status": True,
        "code": status.HTTP_200_OK,
        'next': self.get_next_link(),
        'previous': self.get_previous_link(),
        'count': self.count,
        'results': data
    })

In your view all you need to do is to call two functions, i-e paginate_queryset and the one you created in your pagination class get_paginated_response. "pagination_queryset" takes queryset as parameter and than pass that result to your serializer, finally call "get_paginated_response" which takes serialized data as parameter and in result return response.

page = self.paginate_queryset(query_set)
serializer_class = <Your Serializer>(page, many=True,)
return self.get_paginated_response(serializer_search_user.data)

Finally declare your custom serialization class in "settings.py".

REST_FRAMEWORK = {
      'DEFAULT_PAGINATION_CLASS':'<your_app>.<your_peckage>.custom_pagination.CustomPagination',
      'PAGE_SIZE': 5
}
like image 33
muak Avatar answered Oct 03 '22 00:10

muak