Fix select_for_update with nullable FK outer join error
Remove select_related('locked_by_user') from select_for_update query
to avoid PostgreSQL error "FOR UPDATE cannot be applied to the
nullable side of an outer join". Username is now fetched via lazy load.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -486,6 +486,7 @@ def add_showcase_kit_to_cart(request, kit_id):
|
|||||||
# Атомарная проверка и создание блокировки (предотвращает race condition)
|
# Атомарная проверка и создание блокировки (предотвращает race condition)
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
# Блокируем строки резервов для этого комплекта на уровне БД
|
# Блокируем строки резервов для этого комплекта на уровне БД
|
||||||
|
# Примечание: нельзя использовать select_related с nullable FK при select_for_update
|
||||||
reservations = Reservation.objects.select_for_update().filter(
|
reservations = Reservation.objects.select_for_update().filter(
|
||||||
product_kit=kit,
|
product_kit=kit,
|
||||||
status='reserved'
|
status='reserved'
|
||||||
@@ -496,13 +497,15 @@ def add_showcase_kit_to_cart(request, kit_id):
|
|||||||
cart_lock_expires_at__gt=timezone.now()
|
cart_lock_expires_at__gt=timezone.now()
|
||||||
).exclude(
|
).exclude(
|
||||||
locked_by_user=request.user
|
locked_by_user=request.user
|
||||||
).select_related('locked_by_user').first()
|
).first()
|
||||||
|
|
||||||
if existing_lock:
|
if existing_lock:
|
||||||
|
# Получаем username отдельным запросом (избегаем outer join с select_for_update)
|
||||||
|
locked_by_username = existing_lock.locked_by_user.username if existing_lock.locked_by_user else 'другой кассир'
|
||||||
time_left = (existing_lock.cart_lock_expires_at - timezone.now()).total_seconds() / 60
|
time_left = (existing_lock.cart_lock_expires_at - timezone.now()).total_seconds() / 60
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
'success': False,
|
'success': False,
|
||||||
'error': f'Этот букет уже в корзине кассира "{existing_lock.locked_by_user.username}". '
|
'error': f'Этот букет уже в корзине кассира "{locked_by_username}". '
|
||||||
f'Блокировка истечет через {int(time_left)} мин.'
|
f'Блокировка истечет через {int(time_left)} мин.'
|
||||||
}, status=409) # 409 Conflict
|
}, status=409) # 409 Conflict
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user