我有一个python应用程序,它有很多小的数据库访问功能,使用sqlalchemy。我试图避免在这些函数周围有大量的样板会话处理代码。
我有很多看起来像这样的函数:
def get_ticket_history(Session, ticket_id):
s = Session()
try:
rows = s.query(TicketHistory)\
.filter(TicketHistory.ticket_fk==ticket_id)\
.order_by(TicketHistory.id.desc()).all()
s.commit()
return rows
except:
s.rollback()
raise
finally:
s.close()
我正在尝试重构这些功能,但不确定我还有最好的方法。我目前最好的是:
def execute(Session, fn, *args, **kwargs):
s = Session()
try:
ret = fn(s, *args, **kwargs)
s.commit()
return ret
except:
s.rollback()
raise
finally:
s.close()
def get_ticket_history(self, ticket_id):
def sql_fn(s):
return s.query(TicketHistory)\
.filter(TicketHistory.ticket_fk==ticket_id)\
.order_by(TicketHistory.id.desc()).all()
return execute(self.sentinel_session, sql_fn)
有更好或更惯用的方法吗?也许使用装饰师?
谢谢, 乔恩
答案 0 :(得分:26)
SQLAlchemy文档介绍了使用上下文管理器执行此操作的可能方法。
在此处复制代码段以获得完整性:
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()
这个session_scope
可以干净利用而不需要重复锅炉盘。
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)
答案 1 :(得分:0)
contextlib.contextmanager
装饰器应用于与第一个get_ticket_history
非常相似的函数来创建这样的上下文管理器,用yield
语句替换try和except之间的代码并重命名它,比如说,transaction
。 PEP 343有一个几乎相同的名称示例。
然后,使用带有with语句的上下文管理器重新实现get_ticket_history
。看起来SQLAlchemy已经提供了该函数,方法begin
:
http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html#autocommit-mode
答案 2 :(得分:0)
with
子句的事务处理(开始,提交/回滚)with engine.begin() as connection:
r1 = connection.execute(table1.select())
connection.execute(table1.insert(), {"col1": 7, "col2": "this is some data"})
古老的问题,但我仍然迷迷糊糊,所以这里是文档的相关链接: https://docs.sqlalchemy.org/en/13/core/connections.html
答案 3 :(得分:0)
来自 Sql alchemy 1.4 版: Session 可以用作上下文管理器,而无需使用外部辅助函数。
来自文档的示例
Session = sessionmaker(engine)
with Session() as session:
session.add(some_object)
session.add(some_other_object)
session.commit()
要开始,提交事务并关闭会话,可以应用以下方法。 Session = sessionmaker(引擎)
with Session.begin() as session:
session.add(some_object)
session.add(some_other_object)
# commits transaction, closes session
文档: https://docs.sqlalchemy.org/en/14/orm/session_api.html#sqlalchemy.orm.sessionmaker