Django get_or_create fails to set field when used with iexact

Question:

I’d like to use name__iexact with get_or_create to avoid duplication on user entered fields where possible.

My Provider model has a name field which I use in get_or_create.

The lookup works fine but when creating an instance for the first time as in the p1/Timber example below (the name

Fails:

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

Works as expected here:

>>> 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)

Is __iexact incompatible with the create portion of get_or_create, is this expected behavior (and why), or have I run into a Django bug?

Asked By: owenfi

||

Answers:

According to the documentation, you can try to use default args (haven’t try this code):

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

It makes sense since you can then have the search and the object creation that differs.

Answered By: Stéphane

What you’re seeing is the correct behaviour.

get_or_create is shorthand for ‘get and return the object matching kwargs, if it doesn’t exist, create it using defaults‘. Your lookup is looking for an object where name is a case-insensitive match to 'cedar'. That object exists, so it is returned. Nothing more, nothing less.

Now if there was no match, Stéphane is right, and you would need to specify name in the defaults parameter. All lookups containing the lookup separator __ are stripped from the parameters passed to create().

Answered By: knbk