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