SQLAlchemy + Tornado: How to create scopefunc for SQLAlchemy ScopedSession?

Using a tornado, I want to create a little magic of middleware that ensures that my SQLAlchemy sessions are properly closed / cleaned so that objects are not shared from one query to another. The trick is that since some of my tornado handlers are asynchronous, I can't just share one session for each request.

So, I give up trying to create a ScopedSession that knows how to create a new session for each request. All I have to do is define a scopefunc for my code that can turn the current executable request into a unique key of some type, however I cannot figure out how to get the current request at any given time (outside the scope of the current RequestHandler to which my function does not have access).

Is there something I can do to make this work?

+6
source share
2 answers

You might want to associate Session with the request itself (i.e. do not use scopedsession if this is not convenient). Then you can just say: request.session . You still need to have hooks at the beginning / end for installation / separation.

edit: user scope

 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) 
+4
source

(This is the 2017 answer to the 2011 question). As @Stefano Borini noted, the easiest way in Tornado 4 is to simply allow RequestHandler to implicitly pass the session around . Tornado will monitor the state of the handler instance when using the coroutine decorator templates:

 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 need to reference the SQL Alchemy session asynchronously inside declarative_base (which I would consider as an anti-template, since it confused the model with the application), Amit Matani has a non-working example here .

0
source

Source: https://habr.com/ru/post/904714/


All Articles