3

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

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

  1. 创建数据库会话并将其添加到environ预处理。
  2. 如果没有发生错误,则从获取数据库会话environ并调用后处理。commit()
  3. 如果发生某些错误,请从中获取数据库会话environ并调用后处理。rollback()

第 1 步对我来说很明显:

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 步 - 不是。我找到了后处理任务的例子:

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 生成器,它是这种“后处理”任务的典型代表。

您能否澄清一下它是如何工作的,以及我该如何解决我的问题。

谢谢,鲍里斯。

4

1 回答 1

4

对于第 1 步,我使用 SQLAlchemy范围会话

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()

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

于 2012-08-20T08:23:35.200 回答