I have a QuerySet which contains Page
objects, which have page_number
attribute. The QuerySet is sorted by page_number
, so running [i.page_number for i in pages_query_set]
would return something like, for example, [1,2,3,5,6,10,11,13,16,19,21]
. My task is to write a method that moves the Page
objects so they would be consecutive: in this example, the page that was 5 would become 4, 6 would become 5, 10 would be 6, 11 is 7, 13 is 8, etc.
This is my initial solution, a method inside PageQuerySet
class:
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
Functionally, it works fine. But calling save()
every time really slows it down (probably due to calling database queries every time). I need to find a faster approach. If there had been only one "gap" in this sequence, I would just slice the QuerySet and use something like sliced_qs.update(page_number=models.F('page_number')-gap)
, because I've seen a singular update()
being much faster than several save()
. But the gaps are multiple and pretty random.
So I'm confused. F
objects don't seem to support such looping. It would be great if I could use a callable in update()
, but I haven't found any information about that in docs, nor it works when I try it. Is there a way to apply update()
here? Or maybe some other way to make this method faster?