Update_or_create不会尊重唯一键

时间:2015-07-14 22:48:10

标签: django

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

然后我在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

我正在使用文档https://docs.djangoproject.com/en/1.8/ref/models/querysets/#update-or-create中提供的update_or_create方法,并说通过传入'defaults'字典,在对象存在的情况下要更新的值应该成为诀窍......但是我一直得到一个“IntegrityError at ... column upc并不是唯一的”......

有什么想法吗?

1 个答案:

答案 0 :(得分:48)

update_or_create()分为两部分:用于选择对象的过滤器值以及实际更新的更新值。关键字过滤要更新的对象,默认值是更新的值。如果过滤器不匹配,则会创建一个新对象。

现在你正在过滤所有这些值,因为它们都是作为关键字参数提供的:

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

IntegrityError表示即使存在upc的特定值,也不存在与所有这些过滤器匹配的对象。 Django然后尝试创建对象,但upc不是唯一的,因此这会导致IntegrityError

如果仅过滤upc,该字段将永远不会引发IntegrityError:找到并更新现有对象,或者创建新对象,但是upc是独一无二的。

所以要解决这个问题,只需执行以下操作:

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