Django вручную завершает транзакцию после завершения цикла for

Я пытаюсь запустить цикл 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 () работать для функций без просмотра? Не нашел на это ответа

может быть цикл for запущен после отката, можете ли вы дать перерыв после оператора отката, если хотите пометить его как неудачный

Vaibhav 19.03.2018 13:18

Исправьте пробелы, они повсюду и влияют на правильность кода.

Kevin Christopher Henry 19.03.2018 13:20

@KevinChristopherHenry - верно, исправлено.

user2880391 19.03.2018 13:24

Попробуйте, не ловя Exception. Это могло вызвать нарушение API транзакции (см. Избегайте перехвата исключений внутри atomic!) и маскировать проблему.

Kevin Christopher Henry 19.03.2018 13:36

@KevinChristopherHenry - я пробовал. Получил те же результаты. Я просто знаю, что понял, что он запускается как асинхронная задача на Celery. Не в этом ли причина?

user2880391 19.03.2018 14:04

На самом деле у вас будет такая же проблема с DataError, поскольку это своего рода исключение из базы данных. Если вы хотите продолжить цикл перед лицом ошибок базы данных, вам придется запускать каждую итерацию в собственном блоке atomic(). Я не уверен, что это решит вашу проблему (в остальном код мне кажется правильным), но это необходимый шаг.

Kevin Christopher Henry 20.03.2018 04:00
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
6
314
1

Ответы 1

Итак, видимо -

transaction.atomic():

по умолчанию управляет транзакцией для БД по умолчанию, если не указана другая БД:

transaction.atomic(using='otherDB'):  

Поскольку мы используем более одной БД, а та, над которой я работал, не была задана по умолчанию, мне не хватало «использования».

Другие вопросы по теме