如果引发异常,如何使 Flask-SQLAlchemy 自动回滚会话?

How to make Flask-SQLAlchemy automatically rollback the session if an exception is raised?

我想设置一个使用 Flask-SQLAlchemy 构建的应用程序,以便在视图引发异常时回滚对数据库所做的所有更改,该异常在视图代码之外冒泡(即未在内部捕获)。

即使某些对象在子事务中自动或直接通过 session.commit().

刷新到数据库,我也希望它能正常工作

类似于Django's transaction request wrapping

你可以这样做:

@app.teardown_request
def teardown_request(exception):
    if exception:
        db.session.rollback()
    db.session.remove()

查看 here 以获得 teardown_request 信息。如果您处于调试模式,您可能需要设置 PRESERVE_CONTEXT_ON_EXCEPTION 配置变量。

您可以在自定义错误处理程序中包含回滚...

@app.errorhandler(500)
def internal_error(error):
    db.session.rollback()
    return render_template('500.html'), 500

请参阅“自定义错误页面”部分下的 here

启发,对我有用的最可靠的解决方案是附加一个专门捕获 SQLAlchemy 异常并发出回滚的错误处理程序。

from sqlalchemy import exc
@app.errorhandler(exc.SQLAlchemyError)
def handle_db_exceptions(error):
    #log the error: app.logger.error(error)
    db.session.rollback()

@app.teardown_request 挂钩方法似乎没有及时修复处于不良状态的数据库连接,之后它被后来的请求从数据库连接池中拉出重新使用。 errorhandler 方法在重新使用连接之前捕获连接,并且通过将其范围限制在 SQLAlchemy 引发的 class 错误范围内,感觉更精确。