Hmm, bra fråga. Dokumentationen innebär att det lämpliga undantaget skulle vara ett TransactionManagementError
:
Men källkoden ger en stark ledtråd om att det inte är:
class TransactionManagementError(ProgrammingError):
"""Transaction management is used improperly."""
pass
Observera att detta är ett Programmeringsfel
, som verkligen används för att indikera programmeringsfel (dvs. "används felaktigt").
Om vi tittar på dokumentationen för psycopg (Python-adaptern som används för PostgreSQL-stöd) ser vi att den kommer att höja en psycopg2.extensions.TransactionRollbackError
:
Men vad gör Django med det? Tja, som dokumenterat här
, lindar den standard Python DB API 2.0 undantagen i Django-ekvivalenter och ställer in __cause__
tillskriva det ursprungliga undantaget. Så följande är förmodligen den mest specifika kontrollen du kan göra:
from django.db import OperationalError
from psycopg2.extensions import TransactionRollbackError
for retries in range(0, 3):
try:
with transaction.atomic():
MyModel.objects.update(foo='bar')
except OperationalError as e:
if e.__cause__.__class__ == TransactionRollbackError:
continue
else:
raise
else:
break
Beroende på felinformationen som avslöjas av PostgreSQL (tillgänglig via e .__cause__.diag
) kan det vara möjligt att skriva ett ännu mer specifikt test.
I allmänhet anger Python DB API 2.0-dokumentationen att OperationalError
är verkligen den korrekta undantagstypen för transaktionsproblem, så att fånga upp det skulle förhoppningsvis vara en någorlunda effektiv databasagnostisk lösning.