Ответ 1
EDIT: Это не попытка Optimistic Lock
. Это прямой ответ на предоставленный OP код.
Django предлагает способ выполнения условных запросов. Он также предлагает update_or_create(defaults=None, **kwargs)
который:
Метод
update_or_create
пытается извлечь объект из базы данных на основе данныхkwargs
. Если совпадение найдено, оно обновляет поля, переданные в словаре по умолчанию.Значения в значениях по умолчанию могут быть вызываемыми.
Поэтому мы можем попытаться смешать и сопоставить эти два, чтобы воссоздать поставленный запрос:
obj, created = Account.objects.update_or_create(
id=self.id,
version=self.version,
defaults={
balance: Case(
When(version=self.version, then=F('balance')+amount),
default=amount
),
version: Case(
When(version=self.version, then=F('version')+1),
default=self.version
)
}
)
Разбивка запроса:
update_or_create
попытается получить объект с id=self.id
и version=self.version
в базе данных.
- Найдено: Поля
balance
объекта иversion
будут обновляться со значениями внутри условных выраженийCase
(см. Следующий раздел ответа). - Не найдено. Объект с
id=self.id
иversion=self.version
будет создан, а затемversion=self.version
егоbalance
и поляversion
.
Распределение условных запросов:
-
balance
Запрос:-
Если объект существует,
When
выражение условие будет истинным, поэтомуbalance
поле будет обновляться со значением:# Existing balance # Added amount F('balance') + amount
-
Если объект создается, он будет получать в качестве начального
balance
значениеamount
.
-
-
version
Запрос:-
Если объект существует, условие
When
expression будет истинным, поэтому полеversion
будет обновляться со значением:# Existing version # Next Version F('version') + 1
-
Если объект будет создан, он получит в качестве начальной
version
значениеself.version
(он также может быть исходной версией по умолчанию, такой как1.0.0
).
-
Заметки:
- Вам может потребоваться предоставить аргумент
output_field
для выраженияCase
, посмотрите здесь. - В случае, если определенно определенно предназначено для любопытства относительно выражения
F()
и того, как оно используется, у меня есть пример стиля Q & A: Как выполнить арифметические операции между полями модели в django