djangodjango-rest-framework

How to Paginate within an action in Django Rest Framework


Good afternoon community, I have a question about the Django rest framework page. In this case, I manage to do it in the viewset, but in a class action I have not been able to achieve it.

Attached are images of the responses in the Django rest framework:

Response in viewset

Action:

Response in class action

class PostPageNumberPagination(PageNumberPagination):
    page_size=10

class InterfacesViewSet(viewsets.ModelViewSet):
     
    queryset=Interfaces.objects.all()
    serializer_class=InterfaceSerializer
    pagination_class=PostPageNumberPagination

# La siguiente funcion es un decorador(funciones extra) de la clase RegistrosViewSet para poder manipular los datos que voy a presentar de acuerdo a la URL que se le asigne con el url_path
# El siguiente action actua para poder presentar todos los datos de todos los objetos
    @action(methods=['get'],detail=False,url_path='registros-data-table',url_name='registros_data_table')
    def registros_data_table(self, request):
            paginator=PostPageNumberPagination
            return Response(
                    {
                'id_interface':interface.id_interface,
                'id_EquipoOrigen':interface.id_EquipoOrigen_id,
                'EquipoOrigen':interface.id_EquipoOrigen.nombre,
                'LocalidadOrigen':interface.id_EquipoOrigen.localidad,
                'CategoriaOrigen':interface.id_EquipoOrigen.categoria,
                'id_PuertoOrigen':interface.id_PuertoOrigen_id,
                'PuertoOrigen':interface.id_PuertoOrigen.nombre,
                'estatus':interface.estatus,
                'etiqueta_prtg':interface.etiqueta_prtg,
                'grupo':interface.grupo,
                'if_index':interface.if_index,
                'bw':interface.bw,
                'bw_al':interface.bw_al,
                'id_prtg':interface.id_prtg,
                'ospf':interface.ospf,
                'description':interface.description,
                'id_EquipoDestino':interface.id_EquipoDestino_id,
                'EquipoDestino':interface.id_EquipoDestino.nombre,
                'LocalidadDestino':interface.id_EquipoDestino.localidad,
                'CategoriaDestino':interface.id_EquipoDestino.categoria,
                'id_PuertoDestino':interface.id_PuertoDestino_id,
                'PuertoDestino':interface.id_PuertoDestino.nombre,
                'ultima_actualizacion':interface.ultima_actualizacion,
                    }
                for interface in Interfaces.objects.all()
            )

Update: I made the method provided by the friend @bdoubleu but I get that the objects are not being paginated, that is to say in all the pages the total number of objects appears.

Screenshot without pagination

Screenshot with pagination, but it does not have an effect


Solution

  • First move the response data out into it's own function because you will be using it twice. A better solution would be to create a serializer for the action.

    def get_response_data(paginated_queryset):
        data = {
            'id_interface': interface.id_interface,
            'id_EquipoOrigen': interface.id_EquipoOrigen_id,
            'EquipoOrigen': interface.id_EquipoOrigen.nombre,
            'LocalidadOrigen': interface.id_EquipoOrigen.localidad,
            'CategoriaOrigen': interface.id_EquipoOrigen.categoria,
            'id_PuertoOrigen': interface.id_PuertoOrigen_id,
            'PuertoOrigen': interface.id_PuertoOrigen.nombre,
            'estatus': interface.estatus,
            'etiqueta_prtg': interface.etiqueta_prtg,
            'grupo': interface.grupo,
            'if_index': interface.if_index,
            'bw': interface.bw,
            'bw_al': interface.bw_al,
            'id_prtg': interface.id_prtg,
            'ospf': interface.ospf,
            'description': interface.description,
            'id_EquipoDestino': interface.id_EquipoDestino_id,
            'EquipoDestino': interface.id_EquipoDestino.nombre,
            'LocalidadDestino': interface.id_EquipoDestino.localidad,
            'CategoriaDestino': interface.id_EquipoDestino.categoria,
            'id_PuertoDestino': interface.id_PuertoDestino_id,
            'PuertoDestino': interface.id_PuertoDestino.nombre,
            'ultima_actualizacion': interface.ultima_actualizacion,
        } for interface in queryset
        return data
    

    Then you would paginate in the same way as in rest framework's built in mixins.ListModelMixin.

    @action(methods=['get'],detail=False,url_path='registros-data-table',url_name='registros_data_table')
    def registros_data_table(self, request):
        queryset = Interfaces.objects.all()
    
        page = self.paginate_queryset(queryset)
        if page is not None:
            data = self.get_response_data(page)
            return self.get_paginated_response(data)
    
        data = self.get_response_data(queryset)
        return Response(data)