Manager e QuerySet Personalizzati
I Manager in Django sono lâinterfaccia attraverso cui vengono eseguite le operazioni di query sul database. Ogni modello ha almeno un manager, accessibile tramite objects. Personalizzarli permette di incapsulare query frequenti e mantenere il codice pulito e riutilizzabile.
Il Manager Predefinito
Per impostazione predefinita, Django crea un manager chiamato objects per ogni modello:
from blog.models import Articolo
# 'objects' e il manager predefinito
articoli = Articolo.objects.all()
pubblicati = Articolo.objects.filter(pubblicato=True)
Creare un Manager Personalizzato
Puoi creare manager personalizzati estendendo models.Manager e aggiungendo metodi:
from django.db import models
class ArticoloPubblicatoManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(pubblicato=True)
class ArticoloManager(models.Manager):
def recenti(self):
return self.filter(
pubblicato=True
).order_by('-data_pubblicazione')[:5]
def per_autore(self, nome_autore):
return self.filter(
autore__nome=nome_autore,
pubblicato=True,
)
def piu_letti(self):
return self.filter(
pubblicato=True
).order_by('-visualizzazioni')[:10]
class Articolo(models.Model):
titolo = models.CharField(max_length=200)
pubblicato = models.BooleanField(default=False)
data_pubblicazione = models.DateTimeField()
visualizzazioni = models.PositiveIntegerField(default=0)
# Manager predefinito
objects = ArticoloManager()
# Manager aggiuntivo che restituisce solo articoli pubblicati
pubblicati = ArticoloPubblicatoManager()
# Utilizzo
Articolo.objects.recenti() # ultimi 5 pubblicati
Articolo.objects.per_autore('Mario') # articoli di Mario
Articolo.objects.piu_letti() # top 10 per visualizzazioni
Articolo.pubblicati.all() # solo articoli pubblicati
Override di get_queryset()
Sovrascrivendo get_queryset(), puoi modificare il QuerySet base di un manager:
class AttivoManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(attivo=True)
class SoftDeleteManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(eliminato=False)
class Prodotto(models.Model):
nome = models.CharField(max_length=200)
attivo = models.BooleanField(default=True)
eliminato = models.BooleanField(default=False)
objects = SoftDeleteManager() # manager predefinito: esclude i cancellati
tutti = models.Manager() # per accedere a TUTTI i record
attivi = AttivoManager() # solo prodotti attivi
Il primo manager definito nel modello diventa il manager predefinito, usato anche dallâadmin di Django.
QuerySet Personalizzati
Invece di aggiungere metodi al manager, puoi creare un QuerySet personalizzato. Il vantaggio e che i metodi del QuerySet sono concatenabili:
class ArticoloQuerySet(models.QuerySet):
def pubblicati(self):
return self.filter(pubblicato=True)
def recenti(self):
return self.order_by('-data_pubblicazione')
def per_categoria(self, categoria):
return self.filter(categoria__nome=categoria)
def con_commenti(self):
return self.filter(commenti__isnull=False).distinct()
class Articolo(models.Model):
titolo = models.CharField(max_length=200)
pubblicato = models.BooleanField(default=False)
data_pubblicazione = models.DateTimeField()
categoria = models.ForeignKey('Categoria', on_delete=models.CASCADE)
objects = ArticoloQuerySet.as_manager()
# I metodi del QuerySet sono concatenabili
Articolo.objects.pubblicati().recenti()
Articolo.objects.pubblicati().per_categoria('Python').con_commenti()
Combinare Manager e QuerySet
Per avere sia metodi del manager che del QuerySet concatenabili:
class ArticoloQuerySet(models.QuerySet):
def pubblicati(self):
return self.filter(pubblicato=True)
def recenti(self):
return self.order_by('-data_pubblicazione')
class ArticoloManager(models.Manager):
def get_queryset(self):
return ArticoloQuerySet(self.model, using=self._db)
def pubblicati(self):
return self.get_queryset().pubblicati()
def crea_bozza(self, titolo, contenuto):
return self.create(
titolo=titolo,
contenuto=contenuto,
pubblicato=False,
)
class Articolo(models.Model):
titolo = models.CharField(max_length=200)
contenuto = models.TextField()
pubblicato = models.BooleanField(default=False)
data_pubblicazione = models.DateTimeField(auto_now_add=True)
objects = ArticoloManager()
# Metodi del manager
Articolo.objects.crea_bozza('Nuovo Articolo', 'Contenuto...')
# Metodi del QuerySet, concatenabili
Articolo.objects.pubblicati().recenti()
Conclusione
Manager e QuerySet personalizzati sono strumenti essenziali per mantenere il codice Django pulito e organizzato. I manager incapsulano la logica di accesso ai dati, mentre i QuerySet personalizzati offrono metodi concatenabili per costruire query complesse. Usa as_manager() per convertire rapidamente un QuerySet in manager, oppure combina entrambi per la massima flessibilita.