用于处理SQLAlchemy会话的WSGI应用程序中间件

时间:2012-08-18 15:55:32

标签: sqlalchemy wsgi middleware

我的WSGI应用程序使用SQLAlchemy。我想在请求启动时启动会话,如果它是脏的则提交它并且请求处理成功完成,否则进行回滚。所以,我需要实现Django的TransactionMiddleware

的行为

所以,我想我应该创建WSGI中间件并制作以下​​内容:

  1. 在预处理时创建数据库会话并将其添加到environ
  2. environ获取数据库会话,如果没有发生错误,请在后处理时调用commit()
  3. environ获取数据库会话,并在发布错误时调用rollback()进行后处理。
  4. 第一步对我来说很明显:

    class DbSessionMiddleware:
    def __init__(self, app):
        self.app = app
    
    def __call__(self, environ, start_response):
        environ['db_session'] = create_session()
        return self.app(environ, start_response)
    

    第2步和第3步 - 不是。我找到了example后处理任务:

    class Caseless:
    def __init__(self, app):
        self.app = app
    
    def __call__(self, environ, start_response):
        for chunk in self.app(environ, start_response):
            yield chunk.lower()
    

    它包含评论:

      

    请注意,__call__函数是一个Python生成器,这对于这种“后处理”任务来说是典型的。

    请您澄清它是如何运作的,我如何能够同样解决我的问题。

    谢谢,   鲍里斯。

1 个答案:

答案 0 :(得分:3)

对于第1步,我使用SQLAlchemy scoped sessions

engine = create_engine(settings.DB_URL, echo=settings.DEBUG, client_encoding='utf8')
Base = declarative_base()

sm = sessionmaker(bind=engine)
get_session = scoped_session(sm)

它们为每个get_session()调用返回相同的线程本地会话。

现在步骤2和3如下:

class DbSessionMiddleware:
def __init__(self, app):
    self.app = app

def __call__(self, environ, start_response):
    try:
        db.get_session().begin_nested()
        return self.app(environ, start_response)
    except BaseException:
        db.get_session().rollback()
        raise
    finally:
        db.get_session().commit()

如您所见,我在会话上启动嵌套事务,以便能够回滚已在视图中提交的查询。