Вы можете сделать rollback
для транзакции или откат до точки сохранения непосредственно перед кодом, который вызывает исключение (cr - курсор):
name = uuid.uuid1().hex
cr.execute('SAVEPOINT "%s"' % name)
try:
# your failing query goes here
except Exception:
cr.execute('ROLLBACK TO SAVEPOINT "%s"' % name)
# your alternative code goes here
else:
cr.execute('RELEASE SAVEPOINT "%s"' % name)
В этом коде предполагается, что выполняется транзакция, в противном случае вы не получили бы это сообщение об ошибке.
Django postgresql backend создает курсоры непосредственно из psycopg . Возможно, в будущем они создадут прокси-класс для курсора Django, аналогичный курсору odoo . Они расширяют курсор с помощью следующего кода (self является курсором):
@contextmanager
@check
def savepoint(self):
"""context manager entering in a new savepoint"""
name = uuid.uuid1().hex
self.execute('SAVEPOINT "%s"' % name)
try:
yield
except Exception:
self.execute('ROLLBACK TO SAVEPOINT "%s"' % name)
raise
else:
self.execute('RELEASE SAVEPOINT "%s"' % name)
Таким образом, контекст делает ваш код проще, это будет:
try:
with cr.savepoint():
# your failing query goes here
except Exception:
# your alternative code goes here
и код более читабелен, потому что там нет информации о транзакции.