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

后端 未结 2 400
有刺的猬
有刺的猬 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: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.

提交回复
热议问题