В моем приложении CherryPy + Peewee я часто использую следующий шаблон: запускаю транзакцию, выполняю список операций и возвращаю страницу, показывающую результат. Если во время какой-либо операции что-то пойдет не так, я добавляю строку в таблицу регистрации, а затем перенаправляюсь на страницу, которая показывает эту строку.
Проблема в том, что перенаправление в CherryPy выполняется путем возбуждения исключения, а исключение вызывает откат нескольких транзакций. Откат — это то, что мне нужно для неудачной операции (и всех предыдущих операций, даже если они были успешными), но это не то, что я хочу для ведения журнала.
Например, со следующим кодом, если пользователь переходит на a_page?a=1&b=2&c=3
:
do_this
найдетx != y
и не выполнитshow_message
do_this
обновит одну записьTable1
do_that
найдетx == y
и выполнитshow_message
show_message
добавит одну строку в таблицу журналаMessage
show_message
вызовет исключение, чтобы перенаправить на страницу, которая покажет только что зарегистрированное сообщение
Поскольку во время транзакции возникло исключение, обновление Table1
, сделанное в do_this
, и сообщение, зарегистрированное в show_message
, будут отменены.
Как зафиксировать строки в таблице регистрации и отменить все остальные изменения?
@cherrypy.expose
def a_page(self, a, b, c):
with db.transaction():
self.do_this(a, b)
self.do_that(b, c)
return render('it_worked.html')
def do_this(self, x, y):
if x == y:
self.show_message('Wrong this')
Table1.update(f2=x).where(f1 == y).execute()
def do_that(self, x, y):
if x != y:
self.show_message('Wrong that')
Table1.update(f3=x).where(f1 == z).execute()
def show_message(self, message)
msg = Message.create(msg=message)
raise cherrypy.HTTPRedirect('show_message?id={}'.format(msg.id))
Log.show_log()
нужно знать самую внешнюю транзакцию, чтобы откатить ее, и я пока не знаю, нравится ли мне это. - person stenci   schedule 16.09.2016