Hmm, bella domanda. La documentazione implica che l'eccezione appropriata sarebbe un TransactionManagementError
:
Tuttavia, il codice sorgente dà un forte indizio che non lo è:
class TransactionManagementError(ProgrammingError):
"""Transaction management is used improperly."""
pass
Tieni presente che questo è un ProgrammingError
, che in effetti viene utilizzato per indicare un errore del programmatore (ovvero "usato in modo improprio").
Se osserviamo la documentazione per psycopg (l'adattatore Python utilizzato per il supporto di PostgreSQL) vediamo che genererà un psycopg2.extensions.TransactionRollbackError
:
Ma cosa ci fa Django con quello? Bene, come documentato qui
, racchiude le eccezioni standard Python DB API 2.0 negli equivalenti di Django e imposta il __cause__
attribuire all'eccezione originale. Quindi il seguente è probabilmente il controllo più specifico che puoi effettuare:
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
A seconda dei dettagli dell'errore esposti da PostgreSQL (disponibile tramite e.__cause__.diag
) potrebbe essere possibile scrivere un test ancora più specifico.
In genere, tuttavia, la documentazione Python DB API 2.0 afferma che OperationalError
è davvero il tipo di eccezione corretto per i problemi di transazione, quindi catturarlo si spera sia una soluzione indipendente dal database ragionevolmente efficace.