Here I am trying to do bulk updates in Django:
Problem: In a model, there is a column name position whose value changes according to the drag and drop of the record position. so I am creating the Queryset for that, but not getting the required result, I can update the value of the particular id that got dragged but according to that need to update further makes little tricky using Queryset.
Example:
id name position
1 anil 1
2 ABC 2
3 XYZ 3
4 def 4
now if I drag id 1 to 4th place then I need to shift else by position - 1, Like:
id name position
2 ABC 1
3 XYZ 2
4 def 3
1 anil 4
for this, I was using Queryset of bulk_update but not getting any correct way to do that, please let me know the best way to make update the positions. might be I elaborated on the question too long, but I posted this query thrice, in hope that now I will get the required result.
The model I am using:
class Device(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
position = models.IntegerField(default=0)
def __str__(self):
return self.name
View.py: This is the View I am creating
def put(self, request):
max_len = Device.objects.count()
ids = int(request.query_params.get('id'))
temp = ids
old = int(request.query_params.get('old'))
new = int(request.query_params.get('new'))
if new == old:
return Response("both are equal can't go ahead")
elif new > max_len:
return Response("Invalid Position")
elif old < new:
# code for this condition
elif old > new:
# code for this condition
This is how I was creating this.
Thanks in Advance
CodePudding user response:
I would suggest to use the F
functionality from Django to update all objects in a queryset with arithmetic value rule
Something like:
Model.objects.filter(…).update(order=F('order') - 1)
https://docs.djangoproject.com/en/4.0/ref/models/expressions/
CodePudding user response:
from django.db.models import Case, When, F
from_position = 1
to_position = 4
# First update the row we are moving to have a position of -1
Orderable.objects.filter(position=from_position).update(position=-1)
# Then update all objects in between the from/to positions either up or down
# depending of if the row is moving up or down
Orderable.objects.filter(
position__range=sorted([from_position, to_position])
).update(
position=Case(
When(position__range=(from_position, to_position), then=F('position') - 1),
When(position__range=(to_position, from_position), then=F('position') 1),
)
)
# Then update the position of the original row
Orderable.objects.filter(position=-1).update(position=to_position)