2010-02-26 13 views
15

Allego un metodo al segnale post_save del mio modello Django. In questo modo posso cancellare alcuni elementi della cache ogni volta che il modello viene modificato.Perché il post_save viene sollevato due volte durante il salvataggio di un modello Django?

Il problema che sto avendo è che il segnale viene attivato due volte quando il modello viene salvato. Non fa necessariamente male a nulla (il codice verrà semplicemente cancellato con grazia) ma non può essere corretto.

Un esempio veloce, basta stampare il modello per la console (utilizzando il server dev):

from blog.models import Post 
from django.db.models import signals 

def purge_cache(sender, **kwargs): 
    print 'Purging %s' % sender 

signals.post_save.connect(purge_cache, sender=Post) 

Questo sta usando la stabile 1.1.1 rilascio di Django.

informazioni aggiornate:

Con feedback da parte i commenti di tutti, ho modificato la mia domanda perché la questione è ora scoprendo il motivo per cui il post_save viene attivato due volte. La mia ipotesi al momento è che il mio codice models.py viene importato due volte e che il post_save viene collegato più volte.

Quale sarebbe il modo migliore per capire perché viene importato/eseguito due volte?

+1

Se commentare la linea 'post_delete' Connect, è il segnale' post_save' sollevato due volte? – Desintegr

+2

guardando il codice django e in realtà non invia in save(), sei sicuro di ricevere il segnale post_delete e non post_save due volte? –

+0

@Desintegr - Non posso provarlo al momento ma è una buona idea.Ci proverò stasera e aggiornerò la domanda. Se si verifica ancora dopo aver rimosso post_delete, cambierò la mia domanda in "Perché il segnale post_save viene generato due volte?" :) Forse il codice models.py viene eseguito due volte e il segnale viene collegato più volte? –

risposta

12

Apparentemente, Python is sensitive to the way you import modules. Nel mio caso, non era un problema con alcun codice di importazione all'interno della mia applicazione blog, ma un problema con la configurazione INSTALLED_APPS, che presumo sia utilizzata da Django per eseguire un'importazione iniziale.

Dentro il mio blog applicazione usavo le importazioni quali:

from blog.models import * 

mio settings.py è stato configurato come:

INSTALLED_APPS = (
    'django.contrib.admin', 
    'django.contrib.auth', 
    ...snip... 
    'sorl.thumbnail', 
    'mysite.blog', 
) 

Il prefisso "mysite" è stato aggiunto perché ho avuto in origine percorso di importazione problemi durante la distribuzione del sito. Successivamente ho risolto questo problema (quindi ha funzionato come il server di sviluppo) aggiungendo più percorsi nel mio script WSGI.

Rimozione del prefisso "mysite" dal settings.py risolto il problema:

INSTALLED_APPS = (
    'django.contrib.admin', 
    'django.contrib.auth', 
    ...snip... 
    'sorl.thumbnail', 
    'blog', 
) 
7

Mentre cerca la radice di questo problema, è possibile utilizzare soluzione rapida per evitare la registrazione del segnale due volte:

signals.post_save.connect(my_handler, MyModel, dispatch_uid="path.to.this.module") 

Source.

+1

L'avevo visto ma sembra davvero un trucco che hanno aggiunto perché le persone non potevano essere disturbate a correggere le loro importazioni. Grazie per l'aiuto! –

+2

Penso di non essere d'accordo con @LanceMcNearney sopra. Supponiamo che tu stia scrivendo il codice della biblioteca. Non puoi controllare il modo in cui i consumatori importano il tuo codice. –

+0

Beh, django è noto per la sua retrocompatibilità, questa soluzione consente alle versioni più recenti di evitare il problema e preserva ancora il comportamento delle versioni precedenti –

0

Questo è il ticket relativo a questo numero: Django's signal framework may register listeners more than once #3951. Ora è stato risolto nella versione SVN di Django.

Il problema è esattamente come è: Il modulo che registra il segnale, viene caricato paio di volte, in alcuni casi da diversi percorsi di importazione, così ogni modulo importati questo modo sono erroneamente interpretate dalla Django come diversi moduli che registra lo stesso segnale.

+1

Ho ancora questo problema con django 1.6. Fornire un dispatch_uid non aiuta. – jvannistelrooy

Problemi correlati