Hum, boa pergunta. A documentação implica que a exceção apropriada seria um
TransactionManagementError
:No entanto, o código-fonte dá uma forte pista de que não é:
class TransactionManagementError(ProgrammingError):
"""Transaction management is used improperly."""
pass
Observe que este é um
ProgrammingError
, que de fato é usado para indicar erro do programador (ou seja, "usado incorretamente"). Se examinarmos a documentação do psycopg (o adaptador Python usado para suporte ao PostgreSQL), veremos que ele gerará um
psycopg2.extensions.TransactionRollbackError
:Mas o que o Django faz com isso? Bem, como documentado aqui , ele envolve as exceções padrão do Python DB API 2.0 em equivalentes do Django e define o
__cause__
atribuir à exceção original. Portanto, o seguinte é provavelmente a verificação mais específica que você pode fazer: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
Dependendo dos detalhes do erro expostos pelo PostgreSQL (disponível em
e .__cause__.diag
) pode ser possível escrever um teste ainda mais específico. Geralmente, porém, a documentação do Python DB API 2.0 afirma que
OperationalError
é, de fato, o tipo de exceção correto para problemas de transação, portanto, capturá-lo esperançosamente seria uma solução agnóstica de banco de dados razoavelmente eficaz.