使用龙卷风,我想创建一些中间件魔法,以确保我的SQLAlchemy会话得到正确关闭/清理,以便不会将对象从一个请求共享到下一个请求。诀窍是,由于我的一些龙卷风处理程序是异步的,我不能只为每个请求共享一个会话。
所以我试图创建一个知道如何为每个请求创建一个新会话的ScopedSession。我需要做的就是为我的代码定义一个scopefunc,它可以将当前正在执行的请求转换为某种类型的唯一键,但是我似乎无法弄清楚如何获取当前请求任何一个时间点(当前RequestHandler范围之外,我的函数无权访问)。
我能做些什么来使这项工作?
答案 0 :(得分:4)
您可能希望将Session
与请求本身相关联(即如果不方便,请不要使用scopedsession)。然后你可以说,request.session
。仍然需要在开始/结束处设置钩子以进行设置/拆卸。
编辑:自定义范围函数
def get_current_tornado_request():
# TODO: ask on the Tornado mailing list how
# to acquire the request currently being invoked
Session = scoped_session(sessionmaker(), scopefunc=get_current_tornado_request)
答案 1 :(得分:0)
(这是2017年问题的2017年答案)正如@Stefano Borini所指出的,Tornado 4中最简单的方法就是让RequestHandler隐式pass the session around。使用协程装饰器模式时,Tornado将跟踪处理程序实例状态:
import logging
_logger = logging.getLogger(__name__)
from sqlalchemy import create_engine, exc as sqla_exc
from sqlalchemy.orm import sessionmaker, exc as orm_exc
from tornado import gen
from tornado.web import RequestHandler
from my_models import SQLA_Class
Session = sessionmaker(bind=create_engine(...))
class BaseHandler(RequestHandler):
@gen.coroutine
def prepare():
self.db_session = Session()
def on_finish():
self.db_session.close()
class MyHander(BaseHandler):
@gen.coroutine
def post():
SQLA_Object = self.db_session.query(SQLA_Class)...
SQLA_Object.attribute = ...
try:
db_session.commit()
except sqla_exc.SQLAlchemyError:
_logger.exception("Couldn't commit")
db_session.rollback()
如果你真的需要异步引用declarative_base
内的SQL Alchemy会话(我认为这是反模式,因为它将模型过度耦合到应用程序),Amit Matani有一个不工作的例如here。