Hum, bonne question. La documentation implique que l'exception appropriée serait une TransactionManagementError
:
Cependant, le code source donne un indice fort que ce n'est pas :
class TransactionManagementError(ProgrammingError):
"""Transaction management is used improperly."""
pass
Notez qu'il s'agit d'une ProgrammingError
, qui est en effet utilisé pour indiquer une erreur du programmeur (c'est-à-dire "utilisé de manière incorrecte").
Si nous regardons la documentation de psycopg (l'adaptateur Python utilisé pour le support de PostgreSQL), nous voyons qu'il lèvera un psycopg2.extensions.TransactionRollbackError
:
Mais que fait Django avec ça ? Eh bien, comme documenté ici
, il encapsule les exceptions standard Python DB API 2.0 dans les équivalents Django et définit le __cause__
attribut à l'exception d'origine. La vérification suivante est donc probablement la plus spécifique que vous puissiez effectuer :
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
Selon les détails de l'erreur exposés par PostgreSQL (disponible via e.__cause__.diag
) il peut être possible d'écrire un test encore plus spécifique.
Généralement, cependant, la documentation Python DB API 2.0 indique que OperationalError
est en effet le type d'exception correct pour les problèmes de transaction, donc l'attraper serait, espérons-le, une solution raisonnablement efficace et indépendante de la base de données.