'Django update order field on save

Advancing on this question:

Django model list order field update

I am trying to update all order fields when i update 1 record from a drag and drop list result.

Current implementation using linked question:

class Section(models.Model):
    name = models.CharField()
    order = models.IntegerField(default=0)

    def save(self, *args, **kwargs):
        existing_sections = (
            Section.objects.filter(
                order__gte=self.order
            )
            .exclude(id=self.id)
            .order_by("order")
        )
        existing_sections.update(order=F("order") + 1)

        super(Section, self).save(*args, **kwargs)

Lets say i have 5 fields, with order fields 1 to 5 incrementally.

This code works fine if i add a new Section at the start or end of sequence. It will make first 1 and add 1 to all existing.

But if i want to move from index 3 to index 5, then i will end up with the following as final result. Note the order = 3 is missing and added 6 to the end.

order = 1 
order = 2
order = 4
order = 5
order = 6 


Solution 1:[1]

I guess you should to differentiate between insert and moving. You know is a move because your model pk is not none. On move, you only must change the order of books between the last place and new.

class Section(models.Model):
    name = models.CharField()
    order = models.IntegerField(default=0)

    def save(self, *args, **kwargs):
        is_insert = self.id is not None
        if is_insert:
          # is insert, reorder all
          existing_sections = (
            Section.objects.filter(
                order__gte=self.order
            )
            .exclude(id=self.id)
            .order_by("order")
          )
          existing_sections.update(order=F("order") + 1)
        else:
          # is moving a book
          previous_order = (
            Section
            .objects
            .filter(pk=self.id)
            .values_list('order', flat=true)
            [0])
          Section.objects.filter(
             order_gte=previous_order
          ).filter(
             order_lte=self.order
          ).exclude(id=self.id
          ).update(order=F("order") - 1)

        super(Section, self).save(*args, **kwargs)

Disclaimer: not tested, I just wrote here the code. Take the idea and debug the process

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 dani herrera