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.