Хм, хороший вопрос.Документация подразумевает, что соответствующее исключение будет TransactionManagementError
:
TransactionManagementError
возникает для всех проблем, связанных с транзакциями базы данных.
Однако исходный код дает четкое представление о том, что это не так:
class TransactionManagementError(ProgrammingError):
"""Transaction management is used improperly."""
pass
Обратите внимание, что это ProgrammingError
, что действительноиспользуется для обозначения ошибки программиста (то есть «используется неправильно»).
Если мы посмотрим на документацию для psycopg (адаптер Python, используемый для поддержки PostgreSQL), мы увидим, что он вызовет psycopg2.extensions.TransactionRollbackError
:
исключение psycopg2.extensions.TransactionRollbackError
(подклассы OperationalError
)
Ошибка, вызывающая откат транзакции (взаимоблокировки, ошибки сериализации и т. Д.).
Но что Джанго делает с этим?Ну, как указано здесь , он оборачивает стандартные исключения Python DB API 2.0 в эквивалентах Django и устанавливает атрибут __cause__
в исходное исключение.Таким образом, следующая, вероятно, самая конкретная проверка, которую вы можете сделать:
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
В зависимости от сведений об ошибках, обнаруженных в PostgreSQL (доступных через e.__cause__.diag
), можно написатьеще более конкретный тест.
Как правило, в документации Python DB API 2.0 указывается, что OperationalError
действительно является правильным типом исключения для проблем транзакций, так что отлов этого, надеюсь, будет разумнымэффективное решение, не зависящее от базы данных.