Шаблон сообщения / перенаправления / получения фляги не может восстановиться после ошибки - PullRequest
3 голосов
/ 27 апреля 2019

У меня проблема восстановления после ошибки в функции просмотра 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 и сохраняет данные формы между POST и GET в хранилище flask.session, которое реализуется с помощью файлов cookie HTTP..

Теперь давайте предположим, что где-то есть ошибка, и функция завершается с определенным вводом.Конечно, это не должно произойти.Но когда это происходит, пользовательский опыт ужасен.

Подробно:

  • пользователь отправляет форму (POST)
  • данные формы хранятся вflask.session, то есть как cookie
  • после перенаправления, функция вызывается снова (GET), но теперь она неожиданно завершает работу.Пользователь видит какое-то сообщение об ошибке.Это не хорошо, но ошибки случаются.
  • пользователь перезагружает страницу, намереваясь начать заново, но повторяет эту ошибку снова и снова!

Ключевым моментом является то, чтооператор flask.session.pop удаляет данные формы из хранилища session, но при сбое функции соответствующий файл cookie остается в браузере пользователя.Каждая перезагрузка снова вызывает ошибку.Перезапуск браузера может помочь (в зависимости от флага session.permanent).Единственное гарантированное решение - удалить cookie из браузера вручную.Это фактически делает веб-страницу непригодной для использования.

Я думаю, что могу решить эту проблему, установив очень короткое время жизни файла cookie (15 секунд или около того) или создав новый секретный ключ после каждого перезапуска.Я не пробовал, и это определенно не очень хорошее решение, если cookie-файл сеанса содержит другие данные.

Как сделать функции, подобные приведенным выше, более надежными?

Ответы [ 3 ]

0 голосов
/ 06 мая 2019

Вы управляете сеансом вручную, и это вызывает эту проблему.Пожалуйста, обратите внимание на реализацию мигания сообщения в вашем приложении.Вы можете настроить вспышки, чтобы использовать сеанс на стороне сервера или даже использовать куки.Флэш-сообщения могут храниться на нескольких страницах даже с перенаправлениями.

0 голосов
/ 08 мая 2019

Если нет способа обработать ошибку в самом представлении, мой подход заключается в том, чтобы зарегистрировать обработчик ошибок для всего приложения и управлять здесь сеансом, т. Е. Сбросить в стандартное / безопасное состояние .

Пример:

@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
0 голосов
/ 30 апреля 2019

Я думаю, что в вашем упрощенном примере пропущен важный бит, представляющий, что именно дает сбой.

Если какой-то фрагмент логики может неожиданно завершить работу, вы должны ожидать, что он сделает это и обработает эти случаи.Например, поместив его в обычный try/catch и удалив файл cookie сеанса в блоке catch.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...