2010-08-31 16 views
15

Ich verwende Djangos pre_save-Signal, um auto_now_add zu implementieren. Im Internet gibt es viele Diskussionen darüber, warum Sie es selbst implementieren sollten oder nicht. Ich schätze Kommentare dazu nicht. Weder auf, ob ich die Speicherfunktion neu schreiben sollte (ich habe viele Modelle, die auto_now_add verwenden, so dass die Verwendung von Signalen sinnvoll ist).Django pre_save signal: prüfen, ob die Instanz erstellt wurde nicht aktualisiert, existiert kwargs ['created'] (noch)?

Meine Frage ist:
Ich möchte überprüfen, ob die Instanz erstellt oder aktualisiert wird. Laut einigen Quellen im Internet kann dies durch Testen erfolgen, wenn kwargs['created'] True ist. Allerdings erscheint 'created' nicht in meinem kwargs, obwohl die Instanz neu erstellt wird. Ich habe mich nur gefragt, ob es jemals existiert hat oder dass es magisch verschwunden ist. Ich weiß, ich könnte auch testen, ob kwargs['instance'].id gesetzt ist (das funktioniert tatsächlich für mich), aber ich würde gerne wissen, ob Kwargs ['erstellt'] noch existiert.

+1

Eine Sache zu beachten ist, dass wenn die Instanz-ID/pk gesetzt ist, dies nicht unbedingt bedeutet, dass das Objekt in der Datenbank existiert. Ein häufiges Beispiel wäre, wenn diese Instanzen von __fixtures__ geladen werden. –

+0

@Botondus: Gibt es einen besseren Weg (um das von Ihnen erwähnte Problem zu vermeiden) zu überprüfen, ob die Instanz neu erstellt wird oder ob sie während pre_save aktualisiert wird? – Heyl1

+0

Ja, wenn PK festgelegt ist, müssen Sie die Datenbank tatsächlich abfragen, um sicher zu entscheiden, ob eine Instanz bereits erstellt wurde oder nicht. Etwas wie: MyModel.objects.filter (pk = pk_val) .exists() Es ist tatsächlich in ähnlicher Weise in Django Interna implementiert: http://code.djangoproject.com/browser/django/trunk/django/db/ models/base.py # L493 –

Antwort

16

Nach dem neuesten Django documentation, pre_save sendet kein created Argument. Post_save jedoch does. Ich konnte keine Referenz des Signals finden, das created seit version 1.0 sendet.

+1

Vielen Dank für Ihre Antwort. Ich muss die Quellen falsch gelesen haben und angenommen haben, dass "erstellt" auch im pre_save-Signal erschien. Es macht tatsächlich Sinn, wenn Sie darüber nachdenken. Vielen Dank für die Klärung für mich! – Heyl1

26

Primärschlüsselattribut, das normalerweise von der Datenbank zugewiesen wird, als die Instanz das erste Mal gespeichert wurde. So können Sie etwas wie if instance.pk is None

+0

Funktioniert nicht, wenn Sie einen natürlichen Schlüssel verwenden! – Chris

+0

@phasetwenty Sie können die Tabelle sperren und zusätzlich prüfen, ob ein Datensatz mit einem solchen natürlichen Schlüssel existiert. Oder verwenden Sie Ersatzschlüssel als primär und natürlich als sekundär. –

7

verwenden Ich bin nicht sicher, ob dies der empfohlene Weg ist, aber @ Radagasts Methode hat nicht funktioniert für mich (nicht sicher, ob es, weil ich benutzerdefinierte Pk's verwende).

Ich habe versucht, die folgende (nicht sicher, ob dies der beste Weg ist):

@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" 

Referenz: Django : What is the role of ModelState?

+5

... ist wahr, wirklich? –

1

Mit instance._state.adding die logischste Ansatz ist, wie Sie in der Lage, zu sagen, der Modellzustand existiert oder ist neu, unabhängig davon, ob der Primärschlüssel zugewiesen wurde oder nicht.