Erstellen Sie ein Django-Modell oder aktualisieren Sie es, falls vorhanden

114

Ich möchte ein Modellobjekt wie Person erstellen, wenn die ID der Person nicht vorhanden ist, oder ich erhalte dieses Personenobjekt.

Der Code zum Erstellen einer neuen Person lautet wie folgt:

class Person(models.Model):
    identifier = models.CharField(max_length = 10)
    name = models.CharField(max_length = 20)
    objects = PersonManager()

class PersonManager(models.Manager):
    def create_person(self, identifier):
        person = self.create(identifier = identifier)
        return person

Aber ich weiß nicht, wo ich das vorhandene Personenobjekt überprüfen und erhalten soll.

user1687717
quelle

Antworten:

168

Wenn Sie nach dem Anwendungsfall "Aktualisieren, falls vorhanden, sonst erstellen" suchen, lesen Sie bitte die ausgezeichnete Antwort von @Zags


Django hat bereits ein get_or_create, https://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create

Für Sie könnte es sein:

id = 'some identifier'
person, created = Person.objects.get_or_create(identifier=id)

if created:
   # means you have created a new person
else:
   # person just refers to the existing one
Bakkal
quelle
Ich verwende Django 1.9 und es gibt mir: AttributeError: 'QuerySet'-Objekt hat kein Attribut' update_or_create '
Ofek Gila
1
@OfekGila Das ist seltsam, sowohl der Quellcode als auch die Dokumentation bestätigen QuerySethabenupdate_or_create
Bakkal
1
In meinem Fall habe ich anstelle des Bezeichners eine Gruppe von Feldern, die unique_together bilden. Wie ist die Verwendung für diesen Fall?
Rakmo
191

Es ist unklar, ob Ihre Frage nach der Methode get_or_create (verfügbar ab mindestens Django 1.3) oder der Methode update_or_create (neu in Django 1.7) fragt . Dies hängt davon ab, wie Sie das Benutzerobjekt aktualisieren möchten.

Die Verwendung der Beispiele ist wie folgt:

# In both cases, the call will get a person object with matching
# identifier or create one if none exists; if a person is created,
# it will be created with name equal to the value in `name`.

# In this case, if the Person already exists, its existing name is preserved
person, created = Person.objects.get_or_create(
        identifier=identifier, defaults={"name": name}
)

# In this case, if the Person already exists, its name is updated
person, created = Person.objects.update_or_create(
        identifier=identifier, defaults={"name": name}
)
Zags
quelle
12
+1 für, update_or_createweil es für diesen Anwendungsfall besser ist, als das Objekt erneut get_or_createaufzurufen save().
Bakkal
In meinem Fall habe ich anstelle des Bezeichners eine Gruppe von Feldern, die unique_together bilden. Wie ist die Verwendung für diesen Fall?
Rakmo
1
Der @ OmkarDeshpande-Bezeichner ist nur ein Beispiel. Sie können jede gültige Django-Abfrage übergeben, wie z. B.Person.objects.get_or_create(a=a, b=b, c=c, defaults={"name": name})
Zags
Was ist, wenn ich der erstellten Person mehr Felder als die Standardfelder hinzufügen möchte?
Lo Bellin
@LoBellin Das defaultsArgument für diese Funktionen ist, wo Sie angeben, welche Felder dem Modell hinzugefügt werden sollen. Es hat nichts mit Standardeinstellungen zu tun, die in den Feldern Ihres Modells angegeben sind
Zags
10

Django hat Unterstützung dafür, überprüfen Sie get_or_create

person, created = Person.objects.get_or_create(name='abc')
if created:
    # A new person object created
else:
    # person object already exists
Aamir Adnan
quelle
4

Für nur eine kleine Anzahl von Objekten funktioniert update_or_create gut, aber wenn Sie eine große Sammlung bearbeiten , lässt es sich nicht gut skalieren. update_or_create führt immer zuerst ein SELECT und danach ein UPDATE aus.

for the_bar in bars:
    updated_rows = SomeModel.objects.filter(bar=the_bar).update(foo=100)
        if not updated_rows:
            # if not exists, create new
            SomeModel.objects.create(bar=the_bar, foo=100)

Dies führt bestenfalls nur die erste Aktualisierungsabfrage aus, und nur wenn sie mit null Zeilen übereinstimmt, wird eine weitere INSERT-Abfrage ausgeführt. Dies erhöht Ihre Leistung erheblich, wenn Sie erwarten, dass die meisten Zeilen tatsächlich vorhanden sind.

Es hängt jedoch alles von Ihrem Anwendungsfall ab. Wenn Sie hauptsächlich Einfügungen erwarten, könnte der Befehl massiven_create () eine Option sein.

Andreas Bergström
quelle
3

Ich dachte, ich würde eine Antwort hinzufügen, da Ihr Fragentitel so aussieht, als würde er fragen, wie er erstellt oder aktualisiert werden soll, anstatt wie im Fragetext beschrieben zu erhalten oder zu erstellen.

Wenn Sie ein Objekt erstellen oder aktualisieren wollten, weist die .save () -Methode dieses Verhalten standardmäßig bereits aus den Dokumenten auf :

Django abstrahiert die Notwendigkeit, INSERT- oder UPDATE-SQL-Anweisungen zu verwenden. Insbesondere wenn Sie save () aufrufen, folgt Django diesem Algorithmus:

Wenn das Primärschlüsselattribut des Objekts auf einen Wert festgelegt ist, der True ergibt (dh einen anderen Wert als None oder die leere Zeichenfolge), führt Django ein UPDATE aus. Wenn das Primärschlüsselattribut des Objekts nicht festgelegt ist oder wenn das UPDATE nichts aktualisiert hat, führt Django ein INSERT aus.

Es ist erwähnenswert, dass sie sich im Wesentlichen auf den Fall beziehen, in dem die ID, die Sie dem Objekt gegeben haben, noch nicht in der Datenbank vorhanden ist, wenn sie sagen, dass das UPDATE nichts aktualisiert hat.

Tom Manterfield
quelle
1

Wenn eine der Eingaben beim Erstellen ein Primärschlüssel ist, reicht dies aus:

Person.objects.get_or_create(id=1)

Es wird automatisch aktualisiert, wenn zwei Daten mit demselben Primärschlüssel nicht zulässig sind.

Aminah Nuraini
quelle