在金字塔中管理Pony会话

时间:2017-04-25 05:45:15

标签: python pyramid ponyorm

以下代码引发DatabaseSessionIsOver例外,如this post

中所述
@view_config(route_name='home', renderer='templates/home.jinja2')
@orm.db_session()
def home(self):
    x = models.Entity(...)
    return {'x': x}

我使用return render_to_response('templates/home.jinja2', {'x': x})解决了问题,这是上面提到的帖子中建议的render_template()的Pyramid等价物。

一切运作良好,但我认为有一个更好的解决方案:我认为我应该让Pyramid管理Pony会议。

有可能吗?

我该怎么做?

1 个答案:

答案 0 :(得分:1)

您的问题是您从视图中返回托管对象x,然后在呈现视图的响应之前关闭orm会话。您希望会话包装请求生命周期的更大部分,以便您的托管对象保持更长时间。对于类似数据库会话的事情,补间确实是处理此问题的最佳方法,但还有一些其他方法,例如请求属性request.pony_session和可以关闭会话的完成回调的组合。例如(抱歉,我实际上并不知道小马的api所以你必须填写实际的方法):

def get_pony_session(request):
    session = ...  # load a pony session somehow
    def cleanup(request):
        try:
            if request.exception:
                session.abort()
            else:
                session.commit()
        finally:
            session.close()
    request.add_finished_callback(cleanup)
    return session
config.add_request_method(get_pony_session, 'pony_session', reify=True)

你可以通过pyramid_tm补间和炼金术cookiecutter来了解金字塔是如何做事的,因为它确实是解决这个问题的最佳方法。如果你愿意,你甚至可以编写一个小包装器将pony的会话连接到pyramid_tm。为此,您基本上编写了一个数据管理器[1,2]来管理pony会话并加入pyramid_tm事务(此事务是“虚拟”并且与任何特定数据库无关)和请求属性:

class PonySessionManager:
    def __init__(self, session):
        self.session = session

    def tpc_abort(self, txn):
        self.session.abort()

    def tpc_commit(self, txn):
        self.session.commit()

    def tpc_finish(self, txn):
        self.session.close()

def get_pony_session(request):
    session = ... # load a pony session somehow
    manager = PonySessionManager(session)
    # join the manager to the pyramid_tm transaction via join()
    txn = request.tm.get()
    txn.join(manager)
    return manager

config.add_request_method(get_pony_session, 'pony_session', reify=True)

请注意,数据管理器比需要的更简单,但并不困难。

在一天结束时,您可能会发现以下图表[2]有助于理解金字塔以及您可以使用的钩子。很少您只想包装视图本身而不是更多的管道。

[1] http://zodb.readthedocs.io/en/latest/transactions.html

[2] http://transaction.readthedocs.io/en/latest/datamanager.html

[3] http://docs.pylonsproject.org/projects/pyramid/en/1.8-branch/narr/router.html