Flask post / redirect / get模式无法从错误中恢复

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask post / redirect / get模式无法从错误中恢复相关的知识,希望对你有一定的参考价值。

我在Flask视图函数中有一个错误恢复问题。它的简化版本在这里:

@app.route('/log', methods=['POST', 'GET'])
def elog():
    form = LogForm()
    if form.validate_on_submit():
        flask.session['logformdata'] = form.data
        return flask.redirect(flask.url_for('elog'))

    try:
        formdata = flask.session.pop('logformdata')
    except KeyError:
        return flask.render_template('log.html', form=form)

    log = ... # result of a query
    form.process(data=formdata)
    return flask.render_template('log.html', form=form, log=log)

重要的是它实现了post / redirect / get模式,并将表单数据存储在使用HTTP cookie实现的flask.session存储中的POST和GET之间。

现在让我们假设某处有一个错误,并且该函数在某些输入时崩溃。当然,它不应该发生。但是当它发生时,用户的体验非常糟糕。

详细地:

  • 用户发布表单(POST)
  • 表格数据存储在flask.session中,即作为cookie
  • 重定向后,再次调用该函数(GET),但现在它意外崩溃。用户看到一些错误消息。这不好,但是错误发生了。
  • 用户重新加载想要重新开始的页面,但一次又一次地重复出现相同的错误!

关键点是语句flask.session.popsession存储中删除表单数据,但是当函数崩溃时,相应的cookie仍保留在用户的浏览器中。每次重新加载都会再次触发错误。重新启动浏览器可能会有所帮助(取决于session.permanent标志)。唯一有保障的补救措施是手动从浏览器中删除cookie。这有效地使网页无法使用。

我想我可以通过设置非常短的cookie生命周期(大约15秒)或通过在每次重启后生成新的密钥来缓解这个问题。我没有尝试过,如果会话cookie包含其他数据,那绝对不是一个好的解决方案。

如何使上述功能更强大?

答案

如果在视图本身内无法处理错误,我的方法是针对整个应用程序使用register an error handler,并在此处管理会话,即重置为默认/安全状态。

例:

@app.errorhandler(500)
def handle_internal_server_error(ex):
    """Handle an unexpected and uncaught (500) server error."""

    # Reset session here & display error (e.g. flash or other)

    return  # redirect or render
另一答案

我认为你的简化示例错过了一个重要的部分来表示究竟崩溃的原因。

如果某些逻辑可能意外崩溃,那么你应该期望它能够这样做并处理这些情况。例如,通过将其包装在通常的try/catch中并删除catch块中的会话cookie。

另一答案

您正在手动管理会话,这导致此问题。请查看在您的应用程序中实现Message Flashing。您可以自定义闪存以使用服务器端会话甚至使用cookie。即使使用重定向,也可以跨多个页面维护Flash消息。

以上是关于Flask post / redirect / get模式无法从错误中恢复的主要内容,如果未能解决你的问题,请参考以下文章

Flask

Flask:redirect()函数

Flask 中的 Render Redirect HttpResponse

Flask 中的 Render Redirect HttpResponse

Flask最强攻略 - 跟DragonFire学Flask - 第二篇 Flask 中的 Render Redirect HttpResponse

Flask基础三