Быстрое обновление базы на основе предыдущего значения в Django

У меня есть QuerySet, который содержит Page объекты, которые имеют page_number приписывать. QuerySet отсортирован по page_numberтак работает [i.page_number for i in pages_query_set] вернет что-то вроде, например, [1,2,3,5,6,10,11,13,16,19,21], Моя задача - написать метод, который перемещает Page объекты, чтобы они были последовательными: в этом примере страница, которая была 5, стала бы 4, 6 стала бы 5, 10 была бы 6, 11 - это 7, 13 - это 8, и т. д.

Это мое первоначальное решение, метод внутри PageQuerySet учебный класс:

def validatePageNumbers(self):
    prev_page = 0
    for page in self:
        if page.page_number > prev_page+1:
            page.page_number = prev_page+1
            page.save()
        prev_page = page.page_number

Функционально работает нормально. Но зовет save() каждый раз действительно замедляет его (вероятно, из-за вызова запросов к базе данных каждый раз). Мне нужно найти более быстрый подход. Если бы в этой последовательности был только один "пробел", я бы просто нарезал QuerySet и использовал что-то вроде sliced_qs.update(page_number=models.F('page_number')-gap)потому что я видел единственное число update() гораздо быстрее, чем несколько save(), Но разрывы многочисленны и довольно случайны.

Так что я в замешательстве. F кажется, что объекты не поддерживают такой цикл. Было бы здорово, если бы я мог использовать вызываемый в update(), но я не нашел никакой информации об этом в документах, и это не работает, когда я пытаюсь это сделать. Есть ли способ применить update() Вот? Или может быть какой-то другой способ сделать этот метод быстрее?

1 ответ

Решение этой и многих других узких мест было довольно простым.

from django.db import transaction

with transaction.atomic():
    #do stuff here

Угадай, что все это объединено в одну транзакцию и попадет в базу данных только один раз. Этот ответ очень помог здесь.

Другие вопросы по тегам