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) не работает, или работает лениво!
где подвох?! Посоветуйте что-нибудь?