Avoiding boilerplate session handling code in sqlalchemy functions

前端 未结 3 1330
暗喜
暗喜 2020-12-25 12:50

I have a python application which has lots of small database access functions, using sqlalchemy. I\'m trying to avoid having lots of boilerplate session handling code around

相关标签:
3条回答
  • 2020-12-25 13:34

    morphyn's suggestion to use a context manager is good. You could make such a context manager by applying the contextlib.contextmanager decorator to a function very much like your first get_ticket_history, replacing the code between try and except with a yield statement and renaming it, say, transaction. PEP 343 has a near-identical example of that name.

    Then, use that context manager with the with statement to reimplement get_ticket_history. It looks like SQLAlchemy already provides that function, though, as method begin:

    http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html#autocommit-mode

    0 讨论(0)
  • 2020-12-25 13:40

    transaction handling (begin, commit/rolllback) using with clause

    with engine.begin() as connection:
        r1 = connection.execute(table1.select())
        connection.execute(table1.insert(), {"col1": 7, "col2": "this is some data"})
    

    Old questions, but I still stumbled upon it so here is the relevant link from the docu: https://docs.sqlalchemy.org/en/13/core/connections.html

    0 讨论(0)
  • 2020-12-25 13:42

    The SQLAlchemy docs present a possible way of doing this with context managers.

    http://docs.sqlalchemy.org/en/latest/orm/session_basics.html#when-do-i-construct-a-session-when-do-i-commit-it-and-when-do-i-close-it

    Copying the code snippet here for completeness:

    from contextlib import contextmanager
    
    @contextmanager
    def session_scope():
        """Provide a transactional scope around a series of operations."""
        session = Session()
        try:
            yield session
            session.commit()
        except:
            session.rollback()
            raise
        finally:
            session.close()
    

    This session_scope can be used cleanly without repeating the boiler plate now.

    class ThingOne(object):
        def go(self, session):
            session.query(FooBar).update({"x": 5})
    
    class ThingTwo(object):
        def go(self, session):
            session.query(Widget).update({"q": 18})
    
    def run_my_program():
        with session_scope() as session:
            ThingOne().go(session)
            ThingTwo().go(session)
    
    0 讨论(0)
提交回复
热议问题