'How to rearrange priority field for a django model?

I have a Model with a priority field of type postitive integer. This field is unique and allows me to manage the priority of objects. For example, I want the most important object to have priority one, the second most important to have priority two, etc...

Example:

[
{ "name": "object82",
  "priority": 1
}
{ "name": "object54",
  "priority": 2
}
{ "name": "object12",
  "priority": 3
}
]
class MyObject(models.Model):
    name = models.CharField(_("name"), max_length=255)
    priority = models.PositiveSmallIntegerField(_("priority"), unique=True)

I want to override the object serializer so that if I add a new object with an existing priority, it unpacks the existing objects. (same thing for the path of an existing object)

For example if I take the example above and add:

{ "name": "object22",
  "priority": 2
}

I want the following result:

[
{ "name": "object82",
  "priority": 1          // the priority didn't changed
}
{ "name": "object22",    // my new object
  "priority": 2
}
{ "name": "object54",
  "priority": 3          // the priority had changed
}
{ "name": "object12",    // the priority had changed
  "priority": 4
}
]

I think I have to check first if an object with the same priority exists in the database or not. If not => I save as is

If yes, I have to change the priority of some objects before add the new object.

How to do this ?

Maybe something like:

class MyObjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyObject
        fields = '__all__'
        
    def update(self, instance, validated_data):
        
        target_priority = validated_data.get('priority')

        if MyObject.objects.filter(target_priority).exists():
            existing_priorities = MyObject.objects.filter(priority__gte=target_priority)
            for existing_priority in existing_priorities:
                existing_priority.priority += 1
                existing_priority.save(update_fields=['priority'])
        instance.priority = target_priority
        instance.save(update_fields=['priority'])   


Solution 1:[1]

I was facing a similar problem, and what I have done is that I have a model form and I'm doing the validation in clean function

def clean(self):
    cleaned_data = super().clean()
    priority = cleaned_data.get('priority')

    task = Task.objects.filter(priority__exact=priority)

    while task.exists():
        prev_task_id = task[0].id
        task.update(priority=priority+1)
        priority += 1
        task = Task.objects.filter(priority__exact=priority).exclude(pk=prev_task_id)

        return cleaned_data

I have used the prev_task_id variable for excluding the model that is just got updated. For e.g. let's say we have data

{
    title: 'first one',
    priority: 3
},
{
    title: 'second one',
    priority: 4
}

So now if I got priority 3 and after updating it we will have two tasks with priority 4 so we have to exclude the previous task i.e. 'first one'. We have to only update the second task in next iteration

PS:- This code is written assuming that in the database no duplicate priority exists.

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 localhost_3000