In den Django-Dokumenten sind nur Beispiele zum Überschreiben von save()
und aufgeführt delete()
. Ich möchte jedoch eine zusätzliche Verarbeitung für meine Modelle nur dann definieren, wenn sie erstellt werden . Für alle, die mit Rails vertraut sind, entspricht dies dem Erstellen eines :before_create
Filters. Ist das möglich?
quelle
create
? Das ist eine interessante Lösung, aber es würde nicht funktionieren, wenn das Objekt mitObject(**kwargs).save()
oder einer anderen Variation davon erstellt wird.super(MyModel, self).save(*args, **kwargs)
?self.pk
nicht die beste Option, um zu überprüfen, ob das Objekt neu erstellt oder nur aktualisiert wird. Manchmal geben Sie die Objekt-ID in der Erstellungszeit an (ein angepasster, nicht von der Datenbank generierter Wert wieKSUID
), und dies führt dazu, dass diese Klausel niemals ausgeführt wird. Es gibt einenself._state.adding
Wert, der sicherstellt, ob sie zum ersten Mal gespeichert oder nur aktualisiert wird hilft in diesen Fällen.Ein Beispiel zum Erstellen eines post_save-Signals (von http://djangosnippets.org/snippets/500/ )
from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): """Create a matching profile whenever a user object is created.""" if created: profile, new = UserProfile.objects.get_or_create(user=instance)
Hier finden Sie eine ausführliche Diskussion darüber, ob es am besten ist, Signale oder benutzerdefinierte Speichermethoden zu verwenden. https://web.archive.org/web/20120815022107/http://www.martin-geber.com/thought/2007/10/29/ Django-Signale-gegen-benutzerdefinierte-Speichermethode /
Meiner Meinung nach ist die Verwendung von Signalen für diese Aufgabe robuster, leichter zu lesen, aber länger.
quelle
instance.save()
. In diesem Fall gibt es also auch einen Leistungsverlust, da die Datenbank eine INSERT- und eine UPDATE-Abfrage enthält.Dies ist alt, hat eine akzeptierte Antwort, die funktioniert (Zach's), und eine idiomatischere (Michael Bylstra's), aber da es immer noch das erste Ergebnis bei Google ist, das die meisten Leute sehen, denke ich, brauchen wir einen modernen Best-Django mit mehr Best Practices Stil Antwort hier :
from django.db.models.signals import post_save class MyModel(models.Model): # ... @classmethod def post_create(cls, sender, instance, created, *args, **kwargs): if not created: return # ...what needs to happen on create post_save.connect(MyModel.post_create, sender=MyModel)
Der Punkt ist folgender:
@classmethod
statt markiert, da@staticmethod
Sie höchstwahrscheinlich statische Klassenmitglieder im Code referenzieren müssenNoch sauberer wäre es, wenn Core Django ein tatsächliches
post_create
Signal hätte. (Imho, wenn Sie ein boolesches Argument übergeben müssen, um das Verhalten einer Methode zu ändern, sollten dies 2 Methoden sein.)quelle
Um die Frage wörtlich zu beantworten, ist die
create
Methode im Manager eines Modells eine Standardmethode zum Erstellen neuer Objekte in Django. Um dies zu überschreiben, machen Sie so etwas wiefrom django.db import models class MyModelManager(models.Manager): def create(self, **obj_data): # Do some extra stuff here on the submitted data before saving... # For example... obj_data['my_field'] = my_computed_value(obj_data['my_other_field']) # Now call the super method which does the actual creation return super().create(**obj_data) # Python 3 syntax!! class MyModel(models.model): # An example model my_field = models.CharField(max_length=250) my_other_field = models.CharField(max_length=250) objects = MyModelManager()
In diesem Beispiel überschreibe ich die Methodenmethode des Managers
create
, um eine zusätzliche Verarbeitung durchzuführen, bevor die Instanz tatsächlich erstellt wird.HINWEIS: Code wie
my_new_instance = MyModel.objects.create(my_field='my_field value')
führt diese modifizierte
create
Methode aus, aber Code wiemy_new_unsaved_instance = MyModel(my_field='my_field value')
wird nicht.
quelle
Durch Überschreiben
__init__()
können Sie Code ausführen, wenn das Modell instanziiert wird. Vergessen Sie nicht, die Eltern anzurufen__init__()
.quelle
Sie können die Erstellungsmethode mit einem benutzerdefinierten Manager überschreiben oder der Modellklasse eine Klassenmethode hinzufügen. https://docs.djangoproject.com/de/1.11/ref/models/instances/#creating-objects
quelle
Die bevorzugte Antwort ist richtig, aber der Test, um festzustellen, ob das Objekt erstellt wird, funktioniert nicht, wenn Ihr Modell von UUIDModel abgeleitet ist. Das pk-Feld hat bereits einen Wert.
In diesem Fall können Sie Folgendes tun:
already_created = MyModel.objects.filter(pk=self.pk).exists()
quelle