4

我正在开发一个金字塔应用程序,目前正在从 sqlite 迁移到 postgresql。我发现 postgresql 更严格的事务管理给了我一个糟糕的时间。

我正在使用 pyramid_tm 因为我觉得它很方便。我的大多数问题都发生在我的异步调用期间。我所拥有的是提供动态形式的视图。这个想法是 - 如果我们得到一个对应于数据库行的 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)在呈现我的视图时注册并调用

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 将被跳过。

我有两个问题:

  1. 可以进行transaction.commit()嵌套session.begin_nested()事务吗?我不知道 SQLAlchemy 在哪里结束,而 pyramid_tm 从哪里开始。如果我尝试提交会话,我会得到一个异常,说我只能使用事务管理器提交。另一方面 DBSession.rollback() 工作正常。
  2. 处理这个像

    try:
        #do something with db
    except:
        #oops, let's do something else
    

说得通?我觉得这是“pythonic”,但我不确定这个底层交易是否需要非pythonic手段。

4

1 回答 1

4

调用transaction.commit()您的代码正在提交会话并导致您的contact_person对象在提交后稍后尝试使用它时过期。同样,如果您的user对象在提交的两侧都被触及,您将遇到问题。

正如您所说,如果有异常(NoResultFound),那么您的会话现在无效。您正在寻找的是一个保存点,它支持事务,但不是直接通过begin_nested. 相反,您可以使用transaction.savepoint()组合 withDBSession.flush()来处理错误。

这里的逻辑是flush在数据库上执行 SQL,引发任何错误并允许您回滚保存点。回滚后,会话恢复,你可以继续你的快乐方式。尚未提交任何内容,在请求结束时将该工作留给 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)
于 2013-05-23T14:57:12.087 回答