Django queryset.update(), похоже, действует лениво

У меня есть модель Django с полем с именем 'order':

class Foo(models.Model):
    user = models.ForeignKey(...)
    order = models.PositiveIntegerField(null=True)

    class Meta:
        unique_together = [
            ['user', 'order'],
        ]

    def set_order(self, order):
        self.order = order
        self.save()

Я хочу реализовать метод обновления для моего сериализатора, чтобы иметь возможность переупорядочивать объект. Допустим, текущий порядок нашего объекта равен 5, и мы хотим изменить его на 1. Таким образом, сценарий будет выглядеть так:

1- сделать текущий порядок obj нулевым

2- увеличиваем порядок объектов, которые имеют порядок между порядком нашего obj's текущий_порядок и новый_порядок

3- изменяем порядок obj на new_order

Мой первый код был таким:

def update(self, instance, validated_data):
    user = self.context['request'].user
    current_order = instance.order
    new_order = validated_data['order']

    instance.set_order(None)

    if new_order < current_order:
        qs = PIN.objects.exclude(order__isnull=True).filter(
            user_id=user.id, order__gte=new_order, order__lt=current_order
        ).update(order=F('order')+1)
    else:
        qs = PIN.objects.exclude(order__isnull=True).filter(
            user_id=user.id, order__gt=current_order, order__lte=new_order
        ).update(order=F('order')-1)

Но проблема заключается в порядке обновления объектов в базе данных, и я получаю ошибку уникального ограничения:

('user', 'order') = ('x', '2') already exist

Я прочитал документацию django для метода queryset.update, так вот, метод order_by не является результатом (я использую PostgreSQL).

Я решил изменить свой код следующим образом:

    user = self.context['request'].user
    current_order = instance.order
    new_order = validated_data['order']
    instance.set_order(None)

    if new_order < current_order:
        qs = Foo.objects.exclude(order__isnull=True).filter(
            user_id=user.id, order__gte=new_order, order__lt=current_order
        )
        qs_orders = qs.values_list('order', flat=True)
        qs_objs = list(qs)
        qs.update(order=None)           

        for idx, qs_order in enumerate(qs_orders):
            qs_objs[idx].order = qs_order + 1

        Foo.objects.bulk_update(qs_objs, ['order'])
    else:
        qs = Foo.objects.exclude(order__isnull=True).filter(
            user_id=user.id, order__gt=current_order, order__lte=new_order
        ).update(order=F('order')-1)
        qs_orders = qs.values_list('order', flat=True)
        qs_objs = list(qs)
        qs.update(order=None)           

        for idx, qs_order in enumerate(qs_orders):
            qs_objs[idx].order = qs_order - 1

        Foo.objects.bulk_update(qs_objs, ['order'])

    instance.set_order(new_order)

Теперь, когда я отлаживаю код с помощью pycharm debug (построчно), код работает нормально, но, когда я запускаю проект (например, python manage.py runserver) и вызываю API, ошибка ограничения unique_together появляется снова!

Похоже, что qs.update(order=None) не работает, или работает лениво!

где подвох?! Посоветуйте что-нибудь?

Вернуться на верх