Segnali Django vs. metodo di salvataggio prioritario


89

Ho problemi a capire questo. In questo momento ho alcuni modelli che assomigliano a questo:

 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_gruppo è la media dei punteggi. Quando viene salvata una recensione o un punteggio, devo ricalcolare la media overall_score. In questo momento sto usando un metodo di salvataggio sovrascritto. Ci sarebbero dei vantaggi nell'usare il signal dispatcher di Django?

Risposte:


84

I segnali di salvataggio / eliminazione sono generalmente favorevoli in situazioni in cui è necessario apportare modifiche che non sono completamente specifiche per il modello in questione, o potrebbero essere applicate a modelli che hanno qualcosa in comune o potrebbero essere configurate per l'uso tra modelli.

Un'attività comune nei savemetodi sostituiti è la generazione automatica di slug da un campo di testo in un modello. Questo è un esempio di qualcosa che, se fosse necessario implementarlo per un numero di modelli, trarrebbe vantaggio dall'uso di un pre_savesegnale, in cui il gestore del segnale potrebbe prendere il nome del campo slug e il nome del campo da cui generare lo slug. Una volta che hai installato qualcosa del genere, qualsiasi funzionalità avanzata che metti in atto verrà applicata anche a tutti i modelli, ad esempio cercando lo slug che stai per aggiungere per il tipo di modello in questione, per garantire l'unicità.

Le applicazioni riutilizzabili spesso traggono vantaggio dall'uso di segnali: se la funzionalità che forniscono può essere applicata a qualsiasi modello, in genere (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 utilizzato il pre_savesegnale per gestire un insieme di campi che descrivono una struttura ad albero per il modello che sta per essere creato o aggiornato e il pre_deletesegnale per rimuovere i dettagli della struttura ad albero per l'oggetto da eliminare e il suo intero sottoalbero di oggetti prima di esso e vengono eliminati. Grazie all'uso di segnali, gli utenti non devono aggiungere o modificare saveo deletemetodi sui loro modelli di avere questa gestione fatto per loro, devono solo lasciare che django-MPTT sapere quali modelli lo vogliono gestire.


Cosa succede se il gestore del segnale attiva un'eccezione? Suppongo che non dovrebbero attivare eccezioni, altrimenti non sono una buona misura. Ho sbagliato?
x-yuri

20

Hai chiesto:

Ci sarebbero dei vantaggi nell'usare il signal dispatcher di Django?

Ho trovato questo nei documenti di django:

I metodi del modello sottoposti a override non vengono chiamati nelle operazioni in blocco

Si noti che il metodo delete () per un oggetto non viene necessariamente chiamato quando si eliminano oggetti in blocco utilizzando un QuerySet o come risultato di un'eliminazione a cascata. Per garantire che la logica di eliminazione personalizzata venga eseguita, è possibile utilizzare i segnali pre_delete e / o post_delete.

Sfortunatamente, non c'è una soluzione quando si creano o si aggiornano gli oggetti in blocco, poiché nessuno di save (), pre_save e post_save viene chiamato.

Da: sovrascrittura dei metodi del modello predefiniti


3
La visualizzazione dell'elenco degli amministratori di Django utilizza l'eliminazione di massa ... era confusa fino a quando non si è imbattuto in questo bocconcino.
N.Balauro

7
dice anche "Sfortunatamente, non c'è una soluzione quando si creano o si aggiornano gli oggetti in blocco, poiché nessuno di save (), pre_save e post_save viene chiamato." - quindi non penso che questo sia un compromesso tra questi metodi.
Cory

Questo vale per entrambi i metodi, quindi la risposta è: "no, non c'è alcun vantaggio nell'usare i segnali invece di ignorare il savemetodo"?
Flimm

3

Se utilizzerai i segnali, sarai in grado di aggiornare il punteggio della recensione ogni volta che il modello di punteggio correlato viene salvato. Ma se non ho bisogno di tale funzionalità non vedo alcun motivo per metterlo in segnale, è roba piuttosto legata al modello.



1

Piccola aggiunta dalla documentazione di Django sull'eliminazione di massa ( .delete()metodo sugli QuerySetoggetti):

Tieni presente che questo, quando possibile, verrà eseguito esclusivamente in SQL, quindi i metodi delete () delle singole istanze di oggetti non saranno necessariamente chiamati durante il processo. Se hai fornito un metodo delete () personalizzato su una classe del modello e desideri assicurarti che venga chiamato, dovrai eliminare "manualmente" le istanze di quel modello (ad esempio, iterando su un QuerySet e chiamando delete () su ogni oggetto individualmente) piuttosto che utilizzare il metodo bulk delete () di un QuerySet.

https://docs.djangoproject.com/en/1.11/topics/db/queries/#deleting-objects

E aggiornamento in blocco ( .update()metodo sugli QuerySetoggetti):

Infine, renditi conto che update () esegue un aggiornamento a livello SQL e, quindi, non chiama alcun metodo save () sui tuoi modelli, né emette i segnali pre_save o post_save (che sono una conseguenza della chiamata di Model.save ( )). Se vuoi aggiornare un gruppo di record per un modello che ha un metodo save () personalizzato, passaci sopra e chiama save ()

https://docs.djangoproject.com/en/2.1/ref/models/querysets/#update


Questo non si applica a entrambi?
Flimm
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.