from django.db import IntegrityError
def update_or_create(model, filter_kwargs, update_kwargs)
if not model.objects.filter(**filter_kwargs).update(**update_kwargs):
kwargs = filter_kwargs.copy()
kwargs.update(update_kwargs)
try:
model.objects.create(**kwargs)
except IntegrityError:
if not model.objects.filter(**filter_kwargs).update(**update_kwargs):
raise # re-raise IntegrityError
我想,在问题中提供的代码不是很有说服力:谁想为模型设置id? 让我们假设我们需要这个,我们必须同时操作:
def thread1():
update_or_create(SomeModel, {'some_unique_field':1}, {'some_field': 1})
def thread2():
update_or_create(SomeModel, {'some_unique_field':1}, {'some_field': 2})
随着update_or_create
功能,取决于哪个线程至上,对象将被创建并没有例外更新。这将是线程安全的,但显然有什么用处:取决于SomeModek.objects.get(some__unique_field=1).some_field
竞争条件值可以是1或2
Django提供˚F对象,所以我们可以提升我们的代码:
from django.db.models import F
def thread1():
update_or_create(SomeModel,
{'some_unique_field':1},
{'some_field': F('some_field') + 1})
def thread2():
update_or_create(SomeModel,
{'some_unique_field':1},
{'some_field': F('some_field') + 2})
来源
2013-10-14 09:20:49
Nik
如果另一个进程在两行之间创建对象,create()调用将引发一个IntegrityError。你也不会在create()调用中设置id。 – GDorn 2013-10-14 20:12:38
好的,你说得对,它应该关心IntegrityError。将编辑代码。 – Nik 2013-10-16 14:35:41
请记住,您上面发布的内容已经在django的查询集的开发版中:https://docs.djangoproject.com/en/dev/ref/models/querysets/#update-or-create – 2013-10-31 12:26:01