Быстрое обновление базы на основе предыдущего значения в 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
Угадай, что все это объединено в одну транзакцию и попадет в базу данных только один раз. Этот ответ очень помог здесь.