Segnali Django vs. metodo di salvataggio prioritario
-
05-07-2019 - |
Domanda
Sto avendo problemi a avvolgermi la testa. In questo momento ho alcuni modelli che sembrano un po 'così:
def Review(models.Model)
...fields...
overall_score = models.FloatField(blank=True)
def Score(models.Model)
review = models.ForeignKey(Review)
question = models.TextField()
grade = models.IntegerField()
Una recensione ha diversi "punteggi", il punteggio complessivo è la media dei punteggi. Quando viene salvata una recensione o un punteggio, devo ricalcolare la media complessivo_score. In questo momento sto usando un metodo di salvataggio ignorato. Ci sarebbero dei vantaggi nell'usare il dispatcher di segnali di Django?
Soluzione
I segnali di salvataggio / eliminazione sono generalmente favorevoli in situazioni in cui è necessario apportare modifiche che non sono completamente specifiche del modello in questione, oppure potrebbero essere applicate a modelli che hanno qualcosa in comune o potrebbero essere configurati per l'uso tra i modelli .
Un'attività comune nei metodi save
ignorati è la generazione automatizzata di lumache da alcuni campi di testo in un modello. Questo è un esempio di qualcosa che, se fosse necessario implementarlo per un numero di modelli, trarrebbe beneficio dall'uso di un segnale pre_save
, in cui il gestore del segnale potrebbe prendere il nome del campo slug e il nome di il campo da cui generare la lumaca. Una volta che hai installato qualcosa del genere, tutte le funzionalità avanzate che metterai in atto si applicheranno anche a tutti i modelli, ad es. guardando la lumaca che stai per aggiungere per il tipo di modello in questione, per garantire l'unicità.
Le applicazioni riutilizzabili spesso traggono vantaggio dall'uso dei segnali: se la funzionalità che forniscono può essere applicata a qualsiasi modello, generalmente (a meno che non sia inevitabile) non vorranno che gli utenti debbano modificare direttamente i loro modelli per trarne vantaggio .
Con django-mptt , ad esempio, ho usato pre_save
per gestire un insieme di campi che descrivono una struttura ad albero per il modello che sta per essere creato o aggiornato e il segnale pre_delete
per rimuovere i dettagli della struttura ad albero per l'oggetto da eliminare e il relativo l'intero sottoalbero di oggetti prima di esso e vengono eliminati. A causa dell'uso dei segnali, gli utenti non devono aggiungere o modificare i metodi save
o delete
sui propri modelli per fare eseguire questa gestione per loro, devono solo lasciare django-mptt sa quali modelli vogliono che gestiscano.
Altri suggerimenti
Hai chiesto:
Ci sarebbero dei vantaggi nell'usare il dispatcher di segnali di Django?
L'ho trovato nei documenti di django:
I metodi del modello sovrascritti non vengono chiamati per operazioni in blocco
Nota che il metodo delete () per un oggetto non è necessariamente chiamato quando si eliminano oggetti in blocco utilizzando un QuerySet o come risultato di a eliminazione a cascata. Per garantire l'esecuzione della logica di eliminazione personalizzata, l'utente può usare i segnali pre_eliminazione e / o post_eliminazione.
Sfortunatamente, non esiste una soluzione alternativa durante la creazione o l'aggiornamento oggetti in blocco, poiché nessuno di save (), pre_save e post_save lo sono chiamato.
Se utilizzerai i segnali, sarai in grado di aggiornare il punteggio della recensione ogni volta che viene salvato il modello di punteggio correlato. Ma se non ho bisogno di tale funzionalità non vedo alcun motivo per metterlo in evidenza, è roba piuttosto legata al modello.
È una specie di denormalizzazione. Guarda questa bella soluzione . Definizione del campo di composizione sul posto.
Piccola aggiunta dai documenti Django sull'eliminazione in blocco (metodo .delete ()
su oggetti QuerySet
):
Tieni presente che, quando possibile, questo sarà eseguito esclusivamente in SQL, e così saranno i metodi delete () delle singole istanze di oggetti non necessariamente essere chiamato durante il processo. Se hai fornito a metodo delete () personalizzato su una classe di modello e si desidera assicurarsi che lo sia chiamato, dovrai & # 8220; manualmente & # 8221; elimina le istanze di quel modello (ad es. iterando su un QuerySet e chiamando delete () su ciascuno oggetto singolarmente) anziché utilizzare il metodo bulk (() di a QuerySet.
https://docs.djangoproject.com/ it / 1.11 / temi / db / query / # Eliminazione di oggetti-
E aggiornamento collettivo (metodo .update ()
su oggetti QuerySet
):
Infine, renditi conto che update () fa un aggiornamento a livello SQL e, quindi, non chiama alcun metodo save () sui tuoi modelli, né lo fa emette i segnali pre_save o post_save (che sono una conseguenza di chiamando Model.save ()). Se si desidera aggiornare un gruppo di record per a modello che ha un metodo save () personalizzato, passaci sopra e chiama save ()
https://docs.djangoproject.com/en/ 2.1 / ref / modelli / querysets / # update
I segnali sono utili quando è necessario eseguire un processo a lungo termine e non si desidera bloccare l'utente in attesa del completamento del salvataggio.