【问题标题】:Django ORM how to reference to another row in query?Django ORM如何在查询中引用另一行?
【发布时间】:2014-04-14 20:06:29
【问题描述】:

我有下表“书”:

id     shelf   position (on shelf)
 1        2        3
 2        1        1
 3        1        2
 4        2        2
 5        2        1

我需要将 book4 移动到书架 1 的末尾,因此我需要设置 book4 位置到 [max(position) whereshelf=1] + 1 和位置 where position=[max(position) where Shelf=2] 到 book4 的初始位置(缩小差距)

我试过这个,但 Max 似乎不是这样工作的......

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)

【问题讨论】:

    标签: django django-orm


    【解决方案1】:

    做的更简单:

    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()
    

    【讨论】:

    • 谢谢你的回答,但不是只适合小桌子吗?我的意思是你的递减方法(__gt =),它不会对数百万行征税吗?我非常感谢针对性能调整的建议:)
    • 是的,这对性能很不利。但据我了解,您的问题是强制要求转移书籍以缩小差距。
    • 如果你的桌子很大,最好不要移动书籍,只需将移动书籍的位置设置为max_in_shelf+1
    • 顺序无关紧要,如果像这样与最后一本书缩小差距就可以了(第二本书去了另一个书架):1 [差距] 3 4 -> 1 2(前 4) 3 - 有没有办法做到这一点?
    • 这就是我所需要的!非常感谢!顺便说一句,您可以使用 [0] 而不是 [:1]
    【解决方案2】:

    这将允许您将一本书移动到任何位置

    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()
    

    【讨论】:

    • tnx,但您的示例似乎是在书架内移动书籍,我是否需要更换书架并缩小由该移动引起的位置间隙......
    猜你喜欢
    • 1970-01-01
    • 2016-03-25
    • 2018-12-05
    • 1970-01-01
    • 2020-08-03
    • 2018-05-21
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多