问题
I have the following table 'book':
id shelf position (on shelf)
1 2 3
2 1 1
3 1 2
4 2 2
5 2 1
I need to move book4 to the end of shelf 1, therefore I need to set book4 position to [max(position) where shelf=1] + 1 and position where position=[max(position) where shelf=2] to book4 initial position (to close the gap)
I tried this, but Max doesn't seem to work this way...
Book.objects.filter(shelf=2).annotate(max_position_on_shelf=Max('position'))\
.filter(position=F('max_position_on_shelf'))\
.update(position=F('max_position_on_shelf') + 1)
回答1:
Do it more simple:
from django.db.models import Max
class Book(models.Model):
....
def move(self, shelf_num):
Book.objects.filter(shelf=self.shelf).order_by('-position')[:1].update(position=self.position)
self.position = Book.objects.filter(shelf=shelf_num).aggregate(Max('position')) + 1
self.save()
回答2:
This would allow you to move a book to any position
class Book(models.Model):
...
def move(self, new_position):
current_position = self.position
# No move
if current_position == new_position:
return
# Move book "left" (to a lower position number)
elif current_position > new_position: # 4 -> 2
move = 1
start = new_position # 2
end = current_position # 4
#Move book "right" (to a higher position number)
else: # 2 -> 4
move = -1
start = current_position # 2
end = new_position # 4
Books.objects.filter(
shelf=self.shelf,
position__gte=start,
position__lte=end,
).exclude(
pk=self.pk # Move this manually
).update(
position=F('position') + move
)
self.position = new_position
self.save()
来源:https://stackoverflow.com/questions/23069332/django-orm-how-to-reference-to-another-row-in-query