Django相当于SQL REPLACE

时间:2010-09-09 21:36:19

标签: django django-orm

这个SQL是否有Django ORM最佳实践:

REPLACE app_model SET field_1 = 'some val', field_2 = 'some val';

假设:field_1或field_2在它们上面会有一个唯一的密钥(或者在我的情况下都是两个),否则这将始终评估为INSERT。

编辑:

我现在最好的个人答案就是这个,但这是2-3个查询,其中1应该是可能的:

    from django.core.exceptions import ValidationError
    try:
        Model(field_1='some val',field_2='some val').validate_unique()
        Model(field_1='some val',field_2='some val',extra_field='some val').save()
    except ValidationError:
        Model.objects.filter(field_1='some val',field_2='some val').update(extra_field='some val')

3 个答案:

答案 0 :(得分:11)

你说你想要REPLACE,我认为它应该在插入之前删除任何现有的行,但是你的例子表明你想要更像UPSERT的东西。

AFAIK,django不支持REPLACE(或sqlite的INSERT OR REPLACEUPSERT)。但是你的代码可以合并:

obj, created = Model.objects.get_or_create(field_1='some val', field_2='some_val')
obj.extra_field = 'some_val'
obj.save()

这当然假设field_1field_2或两者都是唯一的(正如您所说)。

这仍然是两个查询(SELECTget_or_createINSERTUPDATEsave,但直到UPSERT类似的解决方案出现(可能不会很长很长时间),它可能是你能做的最好的。

答案 1 :(得分:9)

自Django 1.7起,您可以使用update_or_create方法:

obj, created = Person.objects.update_or_create(
    first_name='John', last_name='Lennon', defaults=updated_values)

答案 2 :(得分:5)

我认为以下内容更有效。

(obj, created) = Model.objects.get_or_create(
   field_1 = 'some val',
   field_2 = 'some_val',
   defaults = {
      'extra_field': 'some_val'
   },
)
if not created and obj.extra_field != 'some_val':
   obj.extra_field = 'some_val'
   obj.save(
      update_fields = [
         'extra_field',
      ],
   )

如果未创建行且需要更新,则只会更新extra_field。