"""Reusable DRF viewset mixins. `IntegrityConflictMixin` converts a DB-level uniqueness *race* into a clean 409. It is not the first line of defense: DRF's auto-generated `UniqueValidator` / `UniqueTogetherValidator` already reject the common (non-concurrent) duplicate with a 400 during `is_valid()`, before the DB is touched. This mixin only catches the genuine concurrent race that slips past validation (two requests both pass `is_valid`, both reach the INSERT) — which would otherwise surface as an uncaught 500. """ from django.db import IntegrityError, transaction from rest_framework import status from rest_framework.response import Response class IntegrityConflictMixin: """Mix into a ModelViewSet to turn an INSERT-time IntegrityError into 409. The create is wrapped in its own `atomic()` block so the catch is savepoint-safe regardless of `ATOMIC_REQUESTS`: the failed INSERT rolls back cleanly and the `except` runs outside the (now-closed) block, so no later query hits a poisoned transaction. Set `conflict_detail` per viewset for a user-facing message. """ conflict_detail = 'This record already exists.' def create(self, request, *args, **kwargs): try: with transaction.atomic(): return super().create(request, *args, **kwargs) except IntegrityError: return Response( {'detail': self.conflict_detail}, status=status.HTTP_409_CONFLICT, )