Оценка кверисетов Django и bulk_update с зависимостями

Предположим, у меня есть следующая модель (сильно упрощенная, ради вопроса):

class DailyMetric(models.Model):
 value_1 = models.FloatField()
 value_2 = models.FloatField()
 ratio = models.FloatField()

Как следует из названия, для каждого дня будет своя запись. Однако value_1 и value_2 зависят от значений предыдущего дня. Допустим, расчет будет следующим:

def update_values(instance, previous_instance):
   if previous_instance:
     instance.value_1 = previous_instance.value_1 + 5
     instance.value_2 = previous_instance.value_2 - 15
     instance.ratio = instance.value_1 / instance.value_2

Естественно, если я обновляю значение для первого числа предыдущего месяца, мне приходится обновлять все последующие экземпляры. По причинам производительности я хочу использовать 'bulk_update':

# member method of the model class
def update_following(self):
  following_entries = self.get_following_entries()
  if not following_entries.exists():
     return

  for i in range(following_entries.count()):
    if i == 0:
      update_values(following_entries[i], self)
    else:
      update_values(following_entries[i], following_entries[i-1])

  DailyMetric.objects.bulk_update(following_entries, ['value_1', 'value_2', 'ratio'])

Однако, похоже, что update_values всегда получает экземпляр со значениями, хранящимися в базе данных, даже если его "питоновское" представление было изменено в предыдущей итерации. Если я предварительно привожу queryset к списку, то все работает, как и ожидалось. Но в моем понимании кверисет оценивается лениво, и при обращении к одному значению запрос должен быть выполнен, а данные затем "помещаются" в локальную память. Если это так, то почему значения "сбрасываются" в значения базы данных на следующей итерации?

Что я здесь упускаю? Есть ли в целом "лучший" способ решить эту задачу? Обновление (возможно) большого количества строк (~1-500), где значения зависят от "предыдущего" экземпляра?

Сабскриптинг делает запрос к базе данных, поэтому, пока значения не сохранены в базе данных, вы получаете старые значения.

Решением является простое приведение его к списку, так что при подзаписи будет получен i-ый элемент списка:

def update_following(self):
  following_entries = list(self.get_following_entries())

  for prev, cur in zip([self, *following_entries], following_entries):
      update_values(cur, prev)

  DailyMetric.objects.bulk_update(following_entries, ['value_1', 'value_2', 'ratio'])
Вернуться на верх