Django ORM how to reference to another row in quer

2019-05-30 01:38发布

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)

2条回答
乱世女痞
2楼-- · 2019-05-30 02:02

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()
查看更多
ゆ 、 Hurt°
3楼-- · 2019-05-30 02:03

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()
查看更多
登录 后发表回答