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

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.