Я пытаюсь запустить цикл for, который проверяет объекты и сохраняет их, и я хочу потерпеть неудачу, если хотя бы один из них не сработал, но только после прохождения всех объектов. Я пробовал разные подходы, но на всех из них - даже если было исключение, хотя бы один объект был сохранен в БД. В последней версии, см. Ниже, я пытаюсь установить
transaction.set_rollback(True)
если хотя бы при возникновении исключения.
try:
is_failed = False
with transaction.atomic():
for identifier, spec in spec_dict.items():
try:
spec_data = {'title':my_title,
'identifier': identifier,
'updated_by': user_id,
'created_by': user_id
}
serializer = SpecSerializer(data=spec_data)
serializer.is_valid(raise_exception=True)
serializer.save()
except DataError as DE:
print("** in DataError")
is_failed = True
pass
except ValidationError as VE:
print("** in ValidationError")
print(str(VE))
is_failed = True
pass
except Exception as Exc:
print("** inside Exception: " + str(Exc))
is_failed = True
pass
if is_failed:
transaction.set_rollback(True)
except IntegrityError:
print("** inside integrity error")
pass
Похоже, что set_rollback не влияет на транзакцию. Стоит отметить, что все наши HTTP-запросы заключены в транзакцию.
Обновлено: Должен ли transaction.atomic () работать для функций без просмотра? Не нашел на это ответа
Исправьте пробелы, они повсюду и влияют на правильность кода.
@KevinChristopherHenry - верно, исправлено.
Попробуйте, не ловя Exception. Это могло вызвать нарушение API транзакции (см. Избегайте перехвата исключений внутри atomic!) и маскировать проблему.
@KevinChristopherHenry - я пробовал. Получил те же результаты. Я просто знаю, что понял, что он запускается как асинхронная задача на Celery. Не в этом ли причина?
На самом деле у вас будет такая же проблема с DataError, поскольку это своего рода исключение из базы данных. Если вы хотите продолжить цикл перед лицом ошибок базы данных, вам придется запускать каждую итерацию в собственном блоке atomic(). Я не уверен, что это решит вашу проблему (в остальном код мне кажется правильным), но это необходимый шаг.






Итак, видимо -
transaction.atomic():
по умолчанию управляет транзакцией для БД по умолчанию, если не указана другая БД:
transaction.atomic(using='otherDB'):
Поскольку мы используем более одной БД, а та, над которой я работал, не была задана по умолчанию, мне не хватало «использования».
может быть цикл for запущен после отката, можете ли вы дать перерыв после оператора отката, если хотите пометить его как неудачный