Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update_or_create wont respect unique key

Tags:

I'm using the following model in Django:

class sfs_upcs(models.Model):   upc = models.CharField(max_length=14, unique=True)   product_title = models.CharField(max_length=150,default="Not Available")   is_buyable = models.NullBooleanField()   price = models.DecimalField(max_digits=8, decimal_places=2,default="0.00")   image_url = models.URLField(default=None)   breadcrumb = models.TextField(default=None)   product_url = models.URLField(default=None)   timestamp = models.DateTimeField(auto_now=True) 

And then I'm using the following code on my views.py:

def insert_record(upc_dict):   upc = upc_dict['upc']   product_title = upc_dict['product_title']   is_buyable = upc_dict['is_buyable']   price = upc_dict['price']   image_url = upc_dict['image_url']   breadcrumb = upc_dict['breadcrumb']   product_url = upc_dict['product_url']   obj, created = sfs_upcs.objects.update_or_create(     defaults={'product_title':product_title,'is_buyable':is_buyable,     'price':price,'image_url':image_url,'breadcrumb':breadcrumb,'product_url':product_url     },     upc = upc,     product_title = product_title,     is_buyable = is_buyable,     price = price,     image_url = image_url,     breadcrumb = breadcrumb,     product_url = product_url)    print obj,created 

I'm using the update_or_create method present in the documentation https://docs.djangoproject.com/en/1.8/ref/models/querysets/#update-or-create and says that by passing into the 'defaults' dictionary the values that you want to UPDATE in case the object exists should make the trick... but I keep getting an "IntegrityError at ... column upc is not unique"...

Any ideas?

like image 714
villancikos Avatar asked Jul 14 '15 22:07

villancikos


1 Answers

There are two parts to update_or_create(): the filter values to select an object, and the update values that are actually updated. The keywords filter the object to update, the defaults are the values that are updated. If there is no match for the filters, a new object is created.

Right now you're filtering on all of these values, since they're all provided as keyword arguments:

upc = upc, product_title = product_title, is_buyable = is_buyable, price = price, image_url = image_url, breadcrumb = breadcrumb, product_url = product_url 

The IntegrityError means that, even though that specific value for upc exists, an object matching all of these filters does not exist. Django then tries to create the object instead, but the upc is not unique, so this causes an IntegrityError.

If you filter on just the upc, that field will never cause an IntegrityError to be raised: either an existing object is found and updated, or a new object is created, but the value for upc is unique.

So to fix this, simply do:

obj, created = sfs_upcs.objects.update_or_create(     # filter on the unique value of `upc`     upc=upc,     # update these fields, or create a new object with these values     defaults={         'product_title': product_title, 'is_buyable': is_buyable,  'price': price,          'image_url': image_url, 'breadcrumb': breadcrumb, 'product_url': product_url,     } ) 
like image 103
knbk Avatar answered Dec 02 '22 16:12

knbk