我使用sqlalchemy和建议的with session_scope()
上下文。
我刚刚发现使用范围发出查询会导致生成的对象以某种方式重新连接到会话,可能在session.commit()
调用中。我已将其缩小到此测试用例,该测试用DetachedInstanceError
:
import sqlalchemy.ext.declarative
import sqlalchemy as sql
import sqlalchemy.orm as sqlorm
from contextlib import contextmanager
DeclarativeBase = sqlalchemy.ext.declarative.declarative_base()
class Test(DeclarativeBase):
__tablename__ = 'test'
id = sql.Column(sql.Integer, sql.Sequence('id_seq'), primary_key=True)
value = sql.Column(sql.Integer)
engine = sql.create_engine('sqlite:///:memory:')
DeclarativeBase.metadata.create_all(engine)
Session = sqlorm.sessionmaker(bind=engine)
@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()
with session_scope() as session:
session.add(Test(value=10))
with session_scope() as session:
items = session.query(Test).all()
print items[0].value
我设法通过向commit
添加session_scope
参数并将session.commit()
更改为if commit: session.commit()
来实现这一目标,但这有点丑陋和错误 - 易于。如果只执行查询,似乎提交应该是无操作。有没有更好,更标准的方法来做到这一点?