SQLAlchemy+Tornado: How to create a scopefunc for SQLAlchemy's ScopedSession?

后端 未结 2 389
有刺的猬
有刺的猬 2021-01-05 07:35

Using tornado, I want to create a bit of middleware magic that ensures that my SQLAlchemy sessions get properly closed/cleaned up so that objects aren\'t shared from one req

相关标签:
2条回答
  • 2021-01-05 08:11

    You might want to associate the Session with the request itself (i.e. don't use scopedsession if it's not convenient). Then you can just say, request.session. Still needs to have hooks at the start/end for setup/teardown.

    edit: custom scoping function

    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)
    
    0 讨论(0)
  • 2021-01-05 08:21

    (This is a 2017 answer to a 2011 question) As @Stefano Borini pointed out, easiest way in Tornado 4 is to just let the RequestHandler implicitly pass the session around. Tornado will track the handler instance state when using coroutine decorator patterns:

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

    If you really really need to asynchronously reference a SQL Alchemy session inside a declarative_base (which I would consider an anti-pattern since it over-couples the model to the application), Amit Matani has a non-working example here.

    0 讨论(0)
提交回复
热议问题