Ошибка Bad Request с флягой, python, HTML, необычное поведение инициализации с flask.request.form

Я пишу веб-приложение, используя флягу, питон и HTML. Моя проблема в том, что при первой загрузке веб-страницы я получаю следующую ошибку:

Плохой запрос Браузер (или прокси) отправил запрос на этот сервер не мог понять.

Я могу получить загрузку страницы, в конце концов, путем "обмана", сначала запуская ее без каких-либо вызовов flask.request.form, а затем вернув их (подробнее см. ниже). Что-то должно произойти неправильно в моей инициализации. Я новичок в flask и с помощью python с HTML.

Предположим, что я работаю из каталога с именем example. У меня есть python script под названием test.py и HTML-шаблон с именем test.html со следующей структурой каталогов:

\example\test.py
\example\templates\test.html

Мой python script test.py:

import sys
import flask, flask.views
app = flask.Flask(__name__)
app.secret_key = "bacon"

class View(flask.views.MethodView):
    def get(self):
        result = flask.request.form['result']
        return flask.render_template('test.html', result=result)
#       return flask.render_template('test.html')
    def post(self):
        return self.get()

app.add_url_rule('/', view_func=View.as_view('main'), methods=['GET', 'POST'])
app.debug = True
app.run()

а мой HTML в test.html равен

<html>
    <head>
    </head>
    <body>
        <form action="/" method="post">
            Enter something into the box:
            <input type="text" name="result"/><br>
            <input type="submit" value="Execute!"/>
        </form>
    </body>
</html>

Шаги по воспроизведению ошибки

1: запустите test.py script и откройте URL в браузере

Running on http://127.0.0.1:5000/

Вы должны увидеть следующую ошибку

Плохой запрос Браузер (или прокси) отправил запрос на этот сервер не мог понять.

2: Прокомментируйте первые 2 строки функции def get(self) и раскомментируйте 3-ю строку функции def get(self), чтобы test.py выглядел следующим образом:

import sys
import flask, flask.views
app = flask.Flask(__name__)
app.secret_key = "bacon"

class View(flask.views.MethodView):
    def get(self):
#       result = flask.request.form['result']
#       return flask.render_template('test.html', result=result)
        return flask.render_template('test.html')
    def post(self):
        return self.get()

app.add_url_rule('/', view_func=View.as_view('main'), methods=['GET', 'POST'])
app.debug = True
app.run()

3: обновите URL-адрес, и вы увидите, что все работает (хотя в конечном итоге я хочу вернуть значение result

4: Теперь переключите строки, которые закомментированы снова. I.e, раскомментируем первые 2 строки функции def get(self) и закомментируем 3-ю строку функции def get(self), чтобы test.py выглядел следующим образом:

import sys
import flask, flask.views
app = flask.Flask(__name__)
app.secret_key = "bacon"

class View(flask.views.MethodView):
    def get(self):
        result = flask.request.form['result']
        return flask.render_template('test.html', result=result)
#       return flask.render_template('test.html')
    def post(self):
        return self.get()

app.add_url_rule('/', view_func=View.as_view('main'), methods=['GET', 'POST'])
app.debug = True
app.run()

5: обновите URL-адрес, и теперь вы увидите, что все будет работать по желанию.

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

Ответ 1

Проблема заключается в том, что вы пытаетесь получить доступ к переменным POST ed в методе, который обрабатывает только запросы GET. Когда вы пытаетесь получить доступ к строке запроса или параметру POST, который не установлен Флажок по умолчанию повысит ошибку BadRequest (поскольку вы прося что-то, что человек, попавший на страницу, не поставлял).

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

Если вам нужно получить доступ к переменной из request.args (GET) или request.form (POST), и вам не нужно ее устанавливать, используйте метод GET, чтобы получить значение, если оно есть ( или None, если он не установлен.

# Will default to None
your_var = request.form.get("some_key")

# Alternately:
your_var = request.form.get("some_key", "alternate_default_value")

Здесь альтернативный способ структурирования вашего кода:

import sys
import flask, flask.views

app = flask.Flask(__name__)

app.secret_key = "bacon"
app.debug = True


class View(flask.views.MethodView):
    def get(self):
        """Enable user to provide us with input"""
        return self._default_actions()

    def post(self):
        """Map user input to our program inputs - display errors if required"""
        result = flask.request.form['result']
        # Alternately, if `result` is not *required*
        # result = flask.request.form.get("result")
        return self._default_actions(result=result)

    def _default_actions(self, result=None):
        """Deal with the meat of the matter, taking in whatever params we need
        to get or process our information"""
        if result is None:
            return flask.render_template("test.html")
        else:
            return flask.render_template("test.html", result=result)

app.add_url_rule('/', view_func=View.as_view('main'), methods=['GET', 'POST'])

if __name__ == "__main__":
    app.run()