2015-03-26 10 views
12

Ich möchte name__iexact mit get_or_create verwenden, um eine Duplizierung auf von Benutzern eingegebenen Feldern zu vermeiden.Django get_or_create kann das Feld nicht setzen, wenn es mit iexact verwendet wird

Mein Provider-Modell hat ein Namensfeld, das ich in get_or_create verwende.

Die Lookup funktioniert gut, aber wenn eine Instanz zum ersten Mal, wie in der p1/Holz Beispiel unten (der Name Erstellen

schlägt fehl:

>>> p1, c1 = Provider.objects.get_or_create(name__iexact="Timber") 
>>> p1, c1 
(<Provider: >, True) 
>>> p1.name 
u'' 

Werke wie hier erwartet:

>>> p2, c2 = Provider.objects.get_or_create(name="Cedar") 
>>> p2.name, c2 
('Cedar', True) 
>>> p3, c3 = Provider.objects.get_or_create(name__iexact="Cedar") 
>>> p3, c3 
(<Provider: Cedar>, False) 
>>> Provider.objects.get_or_create(name__iexact="cedar") 
(<Provider: Cedar>, False) 

Ist __iexact inkompatibel mit dem create-Teil von get_or_create, ist dieses erwartete Verhalten (und warum), oder habe ich einen Django-Bug?

Antwort

13

Was Sie sehen, ist das richtige Verhalten.

get_or_create ist eine Abkürzung für 'Holen Sie sich und geben Sie das Objekt zurück kwargs, wenn es nicht existiert, erstellen Sie es mit defaults'. Ihr Lookup sucht nach einem Objekt, bei dem name keine Übereinstimmung zwischen Groß- und Kleinschreibung ist, sondern 'cedar'. Dieses Objekt existiert und wird zurückgegeben. Nicht mehr, nicht weniger.

Wenn jetzt keine Übereinstimmung gefunden wurde, hat Stéphane Recht, und Sie müssen name im Parameter defaults angeben. Alle Lookups, die das Nachschlagetrennzeichen __ enthalten, werden von den Parametern entfernt, die an create() übergeben werden.

+1

Aha. Dieser letzte Satz ist der Schlüssel. Hier ist es in der Dokumentation: https://docs.djangoproject.com/de/1.7/ref/models/querysets/#get-or-create 'für k, v in kwargs.items() wenn '__' nicht in k' – owenfi

9

Nach dem documentation, können Sie versuchen, Standard-args zu verwenden (nicht diesen Code versuchen):

p1, c1 = Provider.objects.get_or_create(
    defaults={'name':"Timber"}, 
    name__iexact="Timber" 
) 

Es ist sinnvoll, da Sie dann die Suche und die Objekterstellung haben können, die unterschiedlich ist.

Verwandte Themen