2010-08-31 6 views
15

Sto usando il segnale pre_save di Django per implementare auto_now_add. C'è un sacco di discussioni su internet sul perché dovresti o non dovresti implementarlo tu stesso. Non apprezzo i commenti su questo. Non so se dovrei riscrivere la funzione di salvataggio (ho molti modelli che usano auto_now_add quindi usare i segnali ha senso).Segnale pre_save Django: controlla se l'istanza non viene aggiornata, kwargs ['created'] (still) esiste?

La mia domanda è:
Vorrei verificare se l'istanza è stata creata o aggiornata. Secondo alcune fonti su Internet questo può essere fatto testando se kwargs['created'] è True. Tuttavia, 'created' non viene visualizzato nel mio kwargs anche se l'istanza è stata appena creata. Mi stavo chiedendo se è mai esistito o che è scomparso magicamente. So che potrei anche provare se è impostato kwargs['instance'].id (questo di fatto funziona per me), ma mi piacerebbe sapere se kwargs ['created'] esiste ancora.

+1

Una cosa da tenere a mente è che se l'id/pk dell'istanza è impostata, ciò non significa necessariamente che l'oggetto esiste nel database. Un esempio comune sarebbe se quelle istanze sono caricate da __fixtures__. –

+0

@Botondus: Esiste un modo migliore (per evitare il problema che si sta menzionando) per verificare se l'istanza è stata appena creata o se viene aggiornata durante il pre_save? – Heyl1

+0

Sì, se è impostato PK, è necessario interrogare il database per decidere con certezza se un'istanza è già stata creata o meno. Qualcosa come: MyModel.objects.filter (pk = pk_val) .exists() In realtà è implementato in modo simile negli interni di Django: http://code.djangoproject.com/browser/django/trunk/django/db/ models/base.py # L493 –

risposta

16

Secondo l'ultimo Django documentation, pre_save NON invia un argomento created. Post_save tuttavia does. Non sono riuscito a trovare alcun riferimento al segnale che invia created dal version 1.0.

+1

Grazie mille per la risposta. Devo aver letto male le fonti e ho pensato che anche "creato" apparisse nel segnale pre_save. Ha davvero senso quando ci pensi. Grazie per aver chiarito questo per me! – Heyl1

26

Attributo chiave primaria solitamente assegnato dal database quando l'istanza viene salvata per la prima volta. Quindi puoi usare qualcosa come if instance.pk is None

+0

Non funzionerà se stai usando una chiave naturale! – Chris

+0

@phasetwenty È possibile bloccare la tabella e controllare ulteriormente se esiste un record con tale chiave naturale. O utilizzare la chiave surrogata come primaria e naturale come secondaria. –

7

Non sono sicuro se questo è il modo consigliato ma il metodo di @ Radagast non ha funzionato per me (non è sicuro se è perché uso Pk personalizzati).

Ho provato quanto segue (non so se questo è il modo migliore):

@receiver(pre_save, sender=YourModelName, weak=False,) 
def presave_payment_model_check(sender, instance=None, created=False, **kwargs): 
    #Reference: https://stackoverflow.com/questions/11561722/django-what-is-the-role-of-modelstate 
    if instance._state.adding is True: 
     # we would need to create the object 
     print "Creating an object" 
    else: 
     #we are updating the object 
     print "Updating an object" 

Riferimento: Django : What is the role of ModelState?

+5

... è vero, davvero? –

1

Uso instance._state.adding è l'approccio più logico, come si sarà in grado per dire che lo stato del modello esiste o è nuovo, indipendentemente dal fatto che la chiave primaria sia stata assegnata o meno.