Richtige Verwendung von get_or_create?

203

Ich versuche, get_or_create für einige Felder in meinen Formularen zu verwenden, erhalte jedoch eine 500-Fehlermeldung, wenn ich dies versuche.

Eine der Zeilen sieht folgendermaßen aus:

customer.source = Source.objects.get_or_create(name="Website")

Der Fehler, den ich für den obigen Code erhalte, ist:

Cannot assign "(<Source: Website>, False)": "Customer.source" 
   must be a "Source" instance.
Stephen
quelle

Antworten:

353

Aus der Dokumentation get_or_create :

# get_or_create() a person with similar first names.

p, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)},
)

# get_or_create() didn't have to create an object.
>>> created
False

Erläuterung: Felder, deren Ähnlichkeit bewertet werden soll, müssen außerhalb erwähnt werden defaults. Die restlichen Felder müssen in enthalten sein defaults. Wenn das Ereignis CREATE auftritt, werden alle Felder berücksichtigt.

Es sieht so aus, als müssten Sie in ein Tupel zurückkehren, anstatt in eine einzelne Variable. Gehen Sie folgendermaßen vor:

customer.source,created = Source.objects.get_or_create(name="Website")
Bryan Rehbein
quelle
3
FYI erstellt ist ein Boolescher Wert. Richtig, wenn erstellt, Falsch, wenn es abgerufen wird
Josh
3
Ein zusätzliches save()ist überflüssig?
Zypro
@zypro Es ist wie create(), Objekt erstellen und alles in einem Schritt speichern und braucht keinesave()
Amin Mir
32

get_or_create gibt ein Tupel zurück.

customer.source, created = Source.objects.get_or_create(name="Website")
Tobu
quelle
16
Oder, wenn Sie sich nicht für die boolesche Flagge customer.source = Source.objects.get_or_create(name="Website")[0]
interessieren
7
@mipadi Ich würde es vorziehen customer.source, _ = Source.objects.get_or_create(name="Website"), da dadurch die Tatsache, dass ein Tupel zurückgegeben wurde, offensichtlicher wird und zukünftige Fehler vermieden werden .
Solomon Ucko
15

get_or_create() gibt ein Tupel zurück:

customer.source, created  = Source.objects.get_or_create(name="Website")
  • created hat einen booleschen Wert, wird erstellt oder nicht.

  • customer.source hat ein Objekt der get_or_create()Methode.

Tushar.PUCSD
quelle
12

Nach der Antwort von @Tobu und dem Kommentar von @mipadi würde ich auf pythonischere Weise, wenn ich nicht an der erstellten Flagge interessiert wäre, Folgendes verwenden:

customer.source, _ = Source.objects.get_or_create(name="Website")
jbondia
quelle
4

Das Problem, auf das Sie stoßen, ist eine dokumentierte Funktion von get_or_create.

Bei Verwendung anderer Schlüsselwortargumente als "Standard" ist der Rückgabewert von get_or_createeine Instanz. Deshalb werden Ihnen die Parens im Rückgabewert angezeigt.

Sie könnten verwenden customer.source = Source.objects.get_or_create(name="Website")[0], um den richtigen Wert zu erhalten.

Hier ist ein Link für die Dokumentation: http://docs.djangoproject.com/de/dev/ref/models/querysets/#get-or-create-kwargs

wlashell
quelle