Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django get_or_create fails to set field when used with iexact

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?

like image 299
owenfi Avatar asked Mar 26 '15 23:03

owenfi


2 Answers

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

like image 175
knbk Avatar answered Sep 18 '22 17:09

knbk


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.

like image 38
Stéphane Avatar answered Sep 17 '22 17:09

Stéphane