00
:
00
:
00
:
00
•Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

Paginazione

La paginazione e’ essenziale per le API che restituiscono grandi quantita’ di dati. Django REST Framework offre diversi stili di paginazione integrati che permettono di suddividere i risultati in pagine gestibili, migliorando le prestazioni e l’esperienza utente.

Configurazione Globale

La paginazione puo’ essere configurata globalmente nel file settings.py, in modo da applicarsi a tutte le view dell’API.

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 20,
}

Con questa configurazione, tutte le view basate su lista restituiranno automaticamente risultati paginati con 20 elementi per pagina.

PageNumberPagination

E’ lo stile di paginazione piu’ comune. Il client specifica il numero di pagina desiderato tramite un parametro nella query string.

from rest_framework.pagination import PageNumberPagination

class PaginazioneStandard(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'dimensione'  # Permette al client di scegliere
    max_page_size = 100

Esempio di richiesta e risposta:

# Richiesta: GET /api/libri/?page=2&dimensione=5
#
# Risposta:
# {
#     "count": 50,
#     "next": "http://miosito.com/api/libri/?page=3&dimensione=5",
#     "previous": "http://miosito.com/api/libri/?page=1&dimensione=5",
#     "results": [
#         {"id": 6, "titolo": "Il Nome della Rosa"},
#         {"id": 7, "titolo": "1984"},
#         ...
#     ]
# }

La risposta include il conteggio totale degli elementi, i link alla pagina successiva e precedente, e i risultati della pagina corrente.

LimitOffsetPagination

Questo stile permette al client di specificare un limite (quanti elementi) e un offset (da quale posizione iniziare). E’ molto flessibile e comune nelle API REST.

from rest_framework.pagination import LimitOffsetPagination

class PaginazioneLimitOffset(LimitOffsetPagination):
    default_limit = 10
    max_limit = 50
# Richiesta: GET /api/libri/?limit=5&offset=10
#
# Risposta:
# {
#     "count": 50,
#     "next": "http://miosito.com/api/libri/?limit=5&offset=15",
#     "previous": "http://miosito.com/api/libri/?limit=5&offset=5",
#     "results": [
#         {"id": 11, "titolo": "Cent'anni di Solitudine"},
#         {"id": 12, "titolo": "Il Piccolo Principe"},
#         ...
#     ]
# }

offset=10 indica di saltare i primi 10 risultati, mentre limit=5 richiede 5 elementi a partire da quella posizione.

CursorPagination

La paginazione a cursore offre un meccanismo basato su un puntatore opaco che garantisce prestazioni costanti anche con grandi dataset. Non permette di saltare direttamente a una pagina specifica, ma e’ ideale per feed e timeline.

from rest_framework.pagination import CursorPagination

class PaginazioneCursore(CursorPagination):
    page_size = 10
    ordering = '-data_creazione'  # Campo di ordinamento obbligatorio
    cursor_query_param = 'cursore'
# Richiesta: GET /api/libri/
#
# Risposta:
# {
#     "next": "http://miosito.com/api/libri/?cursore=cD0yMDI2LTAx...",
#     "previous": null,
#     "results": [
#         {"id": 50, "titolo": "Ultimo Libro Aggiunto"},
#         ...
#     ]
# }

Il cursore e’ una stringa codificata che DRF gestisce internamente. A differenza degli altri stili, CursorPagination non include il conteggio totale, rendendola piu’ efficiente.

Paginazione Personalizzata

Puoi creare classi di paginazione completamente personalizzate estendendo le classi base.

from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

class PaginazionePersonalizzata(PageNumberPagination):
    page_size = 15
    page_size_query_param = 'per_pagina'
    max_page_size = 50

    def get_paginated_response(self, data):
        return Response({
            'totale': self.page.paginator.count,
            'pagine_totali': self.page.paginator.num_pages,
            'pagina_corrente': self.page.number,
            'per_pagina': self.get_page_size(self.request),
            'prossima': self.get_next_link(),
            'precedente': self.get_previous_link(),
            'risultati': data,
        })

Questa classe personalizzata aggiunge informazioni utili come il numero totale di pagine e la pagina corrente.

Paginazione per Singola View

Puoi assegnare uno stile di paginazione specifico a una singola view, sovrascrivendo la configurazione globale.

from rest_framework import viewsets
from .models import Libro, Articolo
from .serializers import LibroSerializer, ArticoloSerializer

class LibroViewSet(viewsets.ModelViewSet):
    queryset = Libro.objects.all()
    serializer_class = LibroSerializer
    pagination_class = PaginazioneStandard  # Paginazione specifica


class ArticoloViewSet(viewsets.ModelViewSet):
    queryset = Articolo.objects.all()
    serializer_class = ArticoloSerializer
    pagination_class = PaginazioneCursore  # Stile diverso per gli articoli

Per disabilitare la paginazione su una view specifica:

class TutteLeCategorie(viewsets.ModelViewSet):
    queryset = Categoria.objects.all()
    serializer_class = CategoriaSerializer
    pagination_class = None  # Nessuna paginazione

Paginazione con @api_view

Per le view basate su funzione, la paginazione va gestita manualmente:

from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(['GET'])
def lista_libri(request):
    libri = Libro.objects.all()
    paginator = PaginazioneStandard()
    pagina = paginator.paginate_queryset(libri, request)
    serializer = LibroSerializer(pagina, many=True)
    return paginator.get_paginated_response(serializer.data)

Conclusione

La paginazione in Django REST Framework e’ uno strumento flessibile e potente per gestire grandi quantita’ di dati nelle API. PageNumberPagination e’ la scelta piu’ intuitiva per la maggior parte dei casi, LimitOffsetPagination offre maggiore controllo al client, mentre CursorPagination garantisce prestazioni ottimali con dataset molto grandi. La possibilita’ di personalizzare la risposta e configurare la paginazione sia globalmente che per singola view rende DRF adattabile a qualsiasi esigenza.