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