2016-05-12 55 views
1

我正在使用sqlalchemy編寫一些函數。這些功能被稱爲內部交易,如:如何添加一個事件處理程序僅在sqlalchemy中提交事務後觸發一次

def create_order(session, *arg, **kw): 
    # create order object 
    order = Order(xxxx=xxx) 
    session.add(order) 

    # order extra operations 
    order_extra_data = OrderExtraData(yyyy=yyyy) 
    session.add(order_extra_data) 

    # more operations 
    .... 

    # email should be sent to the order's owner 

訂單成功創建後,電子郵件應發送給用戶。但是在create_order的最後,這個事務還沒有被提交,並且可能會被以後的代碼中止。所以這個功能不應該直接發送郵件。相反,它應該註冊一個一次性事件處理程序,只有在提交會話後纔會觸發事件處理程序(如果事務處於回滾或關閉狀態,則不會觸發並清除)。我怎樣才能實現這個?

回答

2

您可以偵聽會話after_commit事件與once=True

def create_order(session, ...): 
    ... 
    @event.listens_for(session, "after_commit", once=True) 
    def _send_email_after_commit(session): 
     send_email() 

如果預計回滾和重複使用會話的道路(以及不聽者回退火後),你」如果發生回滾,還需要刪除事件:

def create_order(session, ...): 
    ... 
    @event.listens_for(session, "after_commit", once=True) 
    def _send_email_after_commit(session): 
     send_email() 

    @event.listens_for(session, "after_soft_rollback", once=True) 
    def _remove_event_listener_on_rollback(session, prev_transaction): 
     event.remove(session, "after_commit", _send_email_after_commit) 
+0

偉大的thx,我也正在閱讀有關事件的文檔。它是否保證調用after_commit和after_soft_rollback(如果直接調用session.close(),是否會觸發after_soft_rollback?)。爲什麼使用after_soft_rollback而不是after_rollback? – jayven

+0

@jayven我相當肯定,一個事務被保證要麼被提交('after_commit')或回滾('after_soft_rollback')。我不確定的唯一情況是交易尚未開始,但幾乎從未發生過。 'Session.close'也無關緊要,因爲在關閉後您將無法重新使用該會話(並且您創建的任何新會話都不會在過去連接到其他會話的偵聽器)。使用'after_soft_rollback',因爲它是對應'session.rollback()'的事件。 'after_rollback'對應於一個SQL'ROLLBACK'。 – univerio

+0

Thx爲您解釋,這可以幫助我很多。 – jayven

相關問題