Почему этот внутренний атомарный блок не откатывается в коде пользовательского представления viewflow
Я создал это пользовательское представление процесса создания, чтобы добавить электронную почту вошедшего пользователя в сохраненный объект, я также добавил блок транзакций, чтобы при неудаче следующего шага (внутри оператора self.activation_done()
) он откатывал изменения в БД внутри form_valid()
и затем отображал ошибку в шаге запуска, поэтому новый экземпляр процесса не сохраняется.
from django.core.exceptions import ValidationError
from django.db import transaction
from django.http import HttpResponseRedirect
from viewflow.flow.views import CreateProcessView, StartFlowMixin
class StarterEmailCreateProcessView(CreateProcessView):
"""
Sets the user email to the process model
"""
def form_valid(self, form, *args, **kwargs):
"""If the form is valid, save the associated model and finish the task."""
try:
with transaction.atomic():
super(StartFlowMixin, self).form_valid(form, *args, **kwargs)
# begin of setting requester email
# https://github.com/viewflow/viewflow/issues/314
self.object.requester_email = self.request.user.email
self.object.save()
# end of setting requester email
self.activation_done(form, *args, **kwargs)
except Exception as ex:
form.add_error(None, ValidationError(str(ex)))
return self.form_invalid(form, *args, **kwargs)
return HttpResponseRedirect(self.get_success_url())
Согласно документации Django, исключение, возникшее внутри транзакции, откатывается
Однако, когда форма выводит сообщение об ошибке, новые экземпляры процесса все еще сохраняются, поэтому я подозреваю, что транзакция не откатывается, и я не знаю почему.
Без выхода self.lock.__enter__()
выглядел подозрительно, поэтому я изменил его на следующий, и он откатился, как и ожидалось
with transaction.atomic(savepoint=True):
signals.task_started.send(sender=self.flow_class, process=self.process, task=self.task)
self.process.save()
lock_impl = self.flow_class.lock_impl(self.flow_class.instance)
self.lock = lock_impl(self.flow_class, self.process.pk)
# self.lock.__enter__()
with self.lock:
self.task.process = self.process
self.task.finished = now()
self.task.save()
signals.task_finished.send(sender=self.flow_class, process=self.process, task=self.task)
signals.flow_started.send(sender=self.flow_class, process=self.process, task=self.task)
self.activate_next()
@kmmbvnr не могли бы вы проверить? Будут ли какие-либо нежелательные последствия после этого изменения?