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

Segnali (Signals)

I segnali (signals) di Django permettono a componenti disaccoppiati dell’applicazione di comunicare tra loro. Quando si verifica un determinato evento, come il salvataggio di un modello o l’arrivo di una richiesta HTTP, Django invia un segnale che può essere intercettato da uno o più ricevitori (receivers). Questo meccanismo è fondamentale per mantenere il codice modulare e pulito.

Come Funzionano i Segnali

Django segue il pattern observer: un mittente (sender) emette un segnale, e tutti i ricevitori registrati per quel segnale vengono eseguiti automaticamente. Il framework mette a disposizione diversi segnali predefiniti.

Segnali dei Modelli

I segnali più utilizzati riguardano le operazioni sui modelli:

from django.db.models.signals import pre_save, post_save, pre_delete, post_delete
from django.dispatch import receiver
from .models import Articolo

@receiver(pre_save, sender=Articolo)
def prima_del_salvataggio(sender, instance, **kwargs):
    """Eseguito prima del salvataggio di un Articolo."""
    if not instance.slug:
        instance.slug = instance.titolo.lower().replace(" ", "-")

@receiver(post_save, sender=Articolo)
def dopo_il_salvataggio(sender, instance, created, **kwargs):
    """Eseguito dopo il salvataggio di un Articolo."""
    if created:
        print(f"Nuovo articolo creato: {instance.titolo}")
    else:
        print(f"Articolo aggiornato: {instance.titolo}")

I segnali pre_delete e post_delete funzionano in modo analogo per le operazioni di eliminazione:

@receiver(pre_delete, sender=Articolo)
def prima_della_cancellazione(sender, instance, **kwargs):
    """Eseguito prima dell'eliminazione di un Articolo."""
    print(f"Sto per eliminare: {instance.titolo}")

@receiver(post_delete, sender=Articolo)
def dopo_la_cancellazione(sender, instance, **kwargs):
    """Eseguito dopo l'eliminazione di un Articolo."""
    # Elimina file associati, ad esempio
    if instance.immagine:
        instance.immagine.delete(save=False)

Segnale m2m_changed

Il segnale m2m_changed viene emesso quando si modificano relazioni many-to-many:

from django.db.models.signals import m2m_changed

@receiver(m2m_changed, sender=Articolo.tags.through)
def tags_modificati(sender, instance, action, **kwargs):
    if action == "post_add":
        print(f"Tag aggiunti all'articolo: {instance.titolo}")
    elif action == "post_remove":
        print(f"Tag rimossi dall'articolo: {instance.titolo}")

Segnali delle Richieste HTTP

Django offre segnali legati al ciclo di vita delle richieste:

from django.core.signals import request_started, request_finished

@receiver(request_started)
def richiesta_iniziata(sender, environ, **kwargs):
    print("Una nuova richiesta HTTP è arrivata")

@receiver(request_finished)
def richiesta_terminata(sender, **kwargs):
    print("La richiesta HTTP è stata completata")

Connessione Manuale con Signal.connect()

Oltre al decoratore @receiver, puoi connettere i segnali manualmente usando il metodo connect():

def gestisci_salvataggio(sender, instance, **kwargs):
    print(f"Modello salvato: {instance}")

post_save.connect(gestisci_salvataggio, sender=Articolo)

Creare Segnali Personalizzati

Puoi definire segnali personalizzati per eventi specifici della tua applicazione:

from django.dispatch import Signal

# Definizione del segnale personalizzato
ordine_completato = Signal()

# Emissione del segnale
def completa_ordine(ordine):
    ordine.stato = "completato"
    ordine.save()
    ordine_completato.send(sender=ordine.__class__, ordine=ordine)

# Ricezione del segnale
@receiver(ordine_completato)
def invia_conferma_ordine(sender, ordine, **kwargs):
    print(f"Invio email di conferma per ordine #{ordine.id}")

Registrazione nei File apps.py

La pratica consigliata in Django 5.x è registrare i segnali nel metodo ready() della configurazione dell’app:

# myapp/apps.py
from django.apps import AppConfig

class MyappConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "myapp"

    def ready(self):
        import myapp.signals  # Importa il modulo con i receiver

Conclusione

I segnali di Django sono uno strumento potente per disaccoppiare la logica dell’applicazione. Permettono di reagire automaticamente a eventi come salvataggio, eliminazione e modifiche ai modelli senza dover modificare il codice originale. Usa i segnali con moderazione: per logica strettamente legata al modello, considera l’override dei metodi save() e delete() come alternativa più esplicita.