这个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')
答案 0 :(得分:11)
你说你想要REPLACE
,我认为它应该在插入之前删除任何现有的行,但是你的例子表明你想要更像UPSERT
的东西。
AFAIK,django不支持REPLACE
(或sqlite的INSERT OR REPLACE
或UPSERT
)。但是你的代码可以合并:
obj, created = Model.objects.get_or_create(field_1='some val', field_2='some_val')
obj.extra_field = 'some_val'
obj.save()
这当然假设field_1
,field_2
或两者都是唯一的(正如您所说)。
这仍然是两个查询(SELECT
为get_or_create
,INSERT
为UPDATE
或save
,但直到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。