2016-12-07 2 views
0

У меня есть 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 и т. Д. .Быстрое обновление базы данных на основе предыдущего значения в Django

Это мое первоначальное решение, метод внутри 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() здесь? Или, может быть, каким-то другим способом сделать этот метод быстрее?

ответ

0

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

from django.db import transaction 

with transaction.atomic(): 
    #do stuff here 

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

Смежные вопросы