我正在开发 Pyramid 应用程序,目前正在从 sqlite 迁移到 postgresql。我发现 postgresql 限制性更强的事务管理让我很不爽。
我正在使用 pyramid_tm,因为我觉得它很方便。我的大部分问题都发生在异步调用期间。我所拥有的是提供动态形式的 View 。这个想法是——如果我们得到一个对应于数据库行的 id,我们就编辑现有的行。否则,我们将添加一个新人。
@view_config(route_name='contact_person_form',
renderer='../templates/ajax/contact_person_form.pt',
permission='view',
request_method='POST')
def contact_person_form(request):
try:
contact_person_id = request.params['contact_person']
DBSession.begin_nested()
contact_person = DBSession.query(ContactPerson).filter(ContactPerson.id == contact_person_id).one()
transaction.commit()
except (NoResultFound, DataError):
DBSession.rollback()
contact_person = ContactPerson(name='', email='', phone='')
return dict(contact_person=contact_person)
我需要开始一个嵌套事务,否则我的惰性请求方法会在 config.add_request_method(get_user, 'user', reify=True)
中注册并在呈现我的 View 时调用
def get_user(request):
userid = unauthenticated_userid(request)
if userid is not None:
user = DBSession.query(Employee).filter(Employee.id == userid).first()
return user
提示事务已中断,员工上的 SELECT 将被跳过。
我有两个问题:
- 可以在
session.begin_nested()
嵌套事务上执行transaction.commit()
吗?我不确切地知道 SQLAlchemy 的结束位置和 pyramid_tm 的开始位置。如果我尝试提交 session ,我会收到一个异常,提示我只能使用事务管理器提交。另一方面,DBSession.rollback() 工作正常。 是否像这样处理
try: #do something with db except: #oops, let's do something else
有意义吗?我感觉这是“pythonic”,但我不确定这种底层事务是否需要非 pythonic 方式。
最佳答案
在您的代码中调用 transaction.commit()
会提交 session 并导致您的 contact_person
对象在提交后稍后尝试使用它时过期。同样,如果您的 user
对象在提交的两边都被触及,您就会遇到问题。
如您所说,如果出现异常 (NoResultFound
),则您的 session 现在无效。您正在寻找的是一个保存点,它支持事务,但不是直接通过 begin_nested
。相反,您可以结合使用 transaction.savepoint()
和 DBSession.flush()
来处理错误。
这里的逻辑是 flush
在数据库上执行 SQL,引发任何错误并允许您回滚保存点。回滚后, session 恢复,你可以继续你的快乐方式。尚未提交任何内容,在请求结束时将该工作留给 pyramid_tm。
try:
sp = transaction.savepoint()
contact_person = DBSession.query(ContactPerson)\
.filter(ContactPerson.id == contact_person_id)\
.one()
DBSession.flush()
except (NoResultFound, DataError):
sp.rollback()
contact_person = ContactPerson(name='', email='', phone='')
return dict(contact_person=contact_person)
关于python - 使用 pyramid_tm 时,SQLAlchemy session.begin_nested() 应该与 transaction.commit() 一起提交吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16710730/