MultipleObjectsReturned mit get_or_create
Schreibe ich eine kleine django-Befehl zum kopieren von Daten aus einer json-API-endpoint in einer Django-Datenbank. An der Stelle, die ich eigentlich erstellen Sie die Objekte, mit obj, created = model.objects.get_or_create(**filters)
ich bin immer ein MultipleObjectsReturned
Fehler. Das ist überraschend für mich, weil mein Verständnis von get_or_create
ist, dass, wenn ich versuche, ein Objekt zu erstellen, das bereits existiert, wird es nur 'get', statt.
Ich bin nicht sicher über die Integrität der Datenbank bin ich Klonen, aber selbst wenn es mehrere identische Objekte in es, wenn ich laden Sie in meinem lokalen Django-Datenbank sollte nicht get_or_create es so machen, dass ich nie mehr als eine Kopie?
Kann jemand dies erklären? Ich bin glücklich, zu geben, mehr ins Detail zu gehen, ich wollte nur nicht, bog den Leser nieder.
get
Suche nach einemunique
element, wenn es mehrelements
es stellt sich die FehlerMultipleObjectsReturned
-, filter-Suche für eine Vielzahl vonelements
und gibt einenlist
von Ihnen.- Eine vergleichende ist hier stackoverflow.com/questions/1541249/...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wie der name schon sagt,
get_or_create
model.objects.get()
s odermodel.objects.create()
s.Es ist konzeptionell äquivalent zu:
Die Quelle ist, wo Sie finden, definitive Antworten auf diese Fragen. Hinweis: suchen Sie
def get_or_create
.Wie Sie sehen können, ist diese Funktion nur Fänge
DoesNotExist
im try/except.get_or_create
nur FängeDoesNotExist
. Aber sollte es nichtself.get(**lookup)
wenn es vorhanden ist? Wenn ja, wie könnte mein Skript immer das zweite Objekt--so ist, wie könnte ich denMultipleObjectsReturned
Ausnahme?get_or_create(name=foo), get_or_create(name=foo, bar=bar), get_or_create(name=foo) # multiple
create()
dann, wenn ich versuchte, Sie zuget()
mit nur spezifisch genug Parameter, um die Suche einzuschränken, um diese beiden Objekte, bekomme ich eine Fehlermeldung. Also, im Grundeget(**params)
ist buchstäblich nur das filtern der Datenbank. Wie eine Artselect-where
SQL-Anweisung.Beispiel-code
Vorstellen, haben Sie das folgende Modell:
und den folgenden code:
get_or_create
In Fall, dass Sie nicht gesehen haben, die code für
get_or_create
:über Webserver...
Nun stellen Sie sich vor, Sie haben einen webserver mit
2
worker-Prozesse, die beide Ihre eigenen gleichzeitigen Zugriff der Datenbank.Wenn das timing richtig geht (oder falsch, je nachdem, wie Sie wollen phrase werden), beide Prozesse kann die lookup-und nicht, den Artikel zu finden. Sie können sowohl das Element erstellt. Alles ist in Ordnung...
MultipleObjectsReturned: get() returned more than one KeyValue -- it returned 2!
Alles in Ordnung ist... bis Sie rufen
get_or_create
ein drittes mal, "zum Dritten mal ist ein Charme", sagen Sie.unique_together
Wie könnte man dieses Problem lösen? Vielleicht erzwingen eine Einschränkung auf der Datenbank-Ebene:
zurück zur Funktion:
Sagen, Sie haben die gleiche Rasse wie zuvor, und Sie beide nicht finden, das Element und gehen Sie zu einfügen, damit Sie eine Transaktion starten, und einer von Ihnen wird das Rennen zu gewinnen, während die anderen werden sehen, eine
IntegrityError
.mysql ?
Beispiel verwendet eine
TextField
, die fürmysql
übersetzt, um einLONGTEXT
(in meinem Fall). Hinzufügen derunique_together
Einschränkung scheitert diesyncdb
.So, kein Glück, müssen Sie sich mit
MultipleObjectsReturned
manuell.mögliche Lösungen
TextField
mit einemCharField
.CharField
kann ein starker hash desTextField
, dass Sie berechnen können, inpre_save
inunique_together
.Anderen situation verursachen könnten, MultipleObjectsReturned Fehler mit get_or_create () - API zu sein scheint, wenn es mehrere threads aufrufen dieser API zur gleichen Zeit mit dem gleichen Satz von query-Parametern.
Allein unter Berufung auf try... catch... erstellen Sie eine einzigartige Reihe, die in Python würde das nicht funktionieren. Wenn Sie versuchen, verwenden Sie diese API, ich denke, du solltest einen passenden Eindeutigkeit auf die entsprechenden Spalten in der Datenbank.
Finden Sie unter: https://code.djangoproject.com/ticket/12579