DRF Pagination with custom ViewSet

2,380 views
Skip to first unread message

Angus

unread,
Mar 15, 2017, 1:46:13 PM3/15/17
to Django REST framework
Hi,

I am using DRF with no Django models, the reason is a legacy database that has limited connection options (pyodbc only). I was hoping somebody could help me figure out how to get the browsable API HTML controls for pagination working.

What I have now is a subclassed GenericViewSet implementing list, along with a custom serializer, custom database layer, and custom paginator:

class MyPaginator(LimitOffsetPagination):

    def paginate_queryset(self, queryset, request, view=None):
        self.limit = self.get_limit(request)
        if self.limit is None:
            return None
        self.offset = self.get_offset(request)
        self.count = queryset.count()
        self.request = request
        if self.count > self.limit and self.template is not None:
            self.display_page_controls = True
        if self.count == 0 or self.offset > self.count:
            return []
            
        #Add the limit/offset to the query
        if self.limit:
            queryset = queryset.limit(self.limit)
        if self.offset:
            queryset = queryset.offset(self.offset)
            
        return list(queryset.execute())

from project.pagination import MyPaginator
from 
project.serializers import MySerializer

class MyViewSet(GenericViewSet):
    serializer_class = MySerializer
    pagination_class = MyPaginator

    def get_queryset(self):
        #Get the objects from the legacy DB
        return Database().table("customers").all()
        
    def list(self, request):
        #Get the queryset (not a django queryset)
        queryset = self.get_queryset()
        
        #Run it through the paginator
        paginator = pagination_class()
        objects = paginator.paginate_queryset(queryset , request)
        
        #Serialize the list of objects
        serializer = self.serializer_class(objects, many=True)
        
        #return Response(serializer.data)
        return paginator.get_paginated_response(serializer.data)


This actually works well and the browsable API shows paginated data with links to the next page. What I don't get is the HTMl pagination controls. The docs say to set display_page_controls as True, but it is and no luck.

Anybody ever tried this, or have any ideas where I should look?

Thanks,

Angus

Xavier Ordoquy

unread,
Mar 15, 2017, 3:21:31 PM3/15/17
to django-res...@googlegroups.com
Hi Angus,

The first thing would be to fire django debug toolbar and investigate whether the pagination is passed to the context.
If it isn’t there’s something in your code that prevents it.
If it is, you’ll have to go through the templates to figure.

Regards,
Xavier Ordoquy,
Linovia.

Angus

unread,
Mar 15, 2017, 5:22:58 PM3/15/17
to Django REST framework
Xavier,

Thanks for the reply. The paginator object was not getting passed to the templates. The problem was in my list function, it was creating a new paginator manually and not through the GenericAPIView methods. So there are a couple ways to fix it:

1. Manually assign the paginator to the GenericAPIView

def list(self, request):
       #Get the queryset (not a django queryset)
       queryset = self.get_queryset()
       
       #Run it through the paginator
       paginator = self.pagination_class()
       objects = paginator.paginate_queryset(queryset, request)
       
       #Serialize the list of objects
       serializer = self.serializer_class(objects, many=True)
       
       self._paginator = paginator
       return paginator.get_paginated_response(serializer.data)

2. Use the GenericAPIView to get the paginator and response

def list(self, request):
    #Get the queryset (not a django queryset)
    queryset = self.get_queryset()

    #Run it through the paginator
    objects = self.paginate_queryset(query)

    #Serialize the list of objects
    serializer = self.get_serializer(objects, many=True)

    return self.get_paginated_response(serializer.data)

Either way the GenericAPIView passes the pagination object to the templates and it work.

Thanks again,

Angus
Reply all
Reply to author
Forward
0 new messages