Обновите несколько полей в экземпляре модели, используя select_for_update в Django - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть класс модели с именем DataObj и некоторый метод copmlex, который вначале извлекает экземпляр DataObj, выполняет некоторые вычисления и обновляет его поля.

Для обеспечения целостности в параллельной среде мое приложение использует оптимистическую блокировку c с использованием целых чисел поле версии.

Чтобы не обернуть все вычисления в @ atomi c, у меня есть короткая и быстрая функция save_changes:

@transaction.atomic
def save_changes(DataObj dataObj):
    db_instance = DataObj.objects.select_for_update().get(id=dataObj.id, version=dataObj.version)
    # copy all changes from dataObj to db_instance 
    db_instance.save()

, и я вызываю ее из моего сложного метода

def long_update_func(dataobj_id):
    obj = DataObj.objects.get(id=dataobj_id)
    # perform several calculations, update fields
    obj.field1 = result_of_calc1()
    ...
    try:
        save_changes(obj)
    except:
        # whoops, version changed
        notify_data_changed_during_calculations()

Вопрос : копирование полей действительно раздражает. Можно ли избежать копирования полей в функции save_changes? У меня есть хороший измененный dataObj с точно таким же идентификатором, который я использую для блокировки строк базы данных в вызове select_for_update.

Могу ли я просто переписать так (или аналогично):

@transaction.atomic
def save_changes(DataObj dataObj):
    db_instance = DataObj.objects.select_for_update().get(id=dataObj.id, version=dataObj.version)
    # save our dataObj, because it has same id as db_instance and therefore its row in db table is locked
    dataObj.save()

?

...