Веб-приложениям часто требуется обрабатывать данные входящих запросов пользователей. Эта полезная нагрузка может иметь форму строк запросов, данных форм и объектов JSON. Flask, как и любая другая веб-инфраструктура, предоставляет доступ к данным запросов.
В этом учебном модуле мы создадим приложение Flask с тремя маршрутами, которое будет принимать строки запросов, данные форм и объекты JSON.
Для данного обучающего руководства вам потребуется следующее:
Для этого учебного модуля мы использовали версии Pipenv v2020.11.15, Python v3.9.0 и Flask v1.1.2.
Чтобы продемонстрировать разные способы использования запросов, мы создадим приложение Flask. Хотя в примере используется упрощенная структура отображения функций и маршрутов, уроки этого учебного модуля можно применить к любым методам организации представлений, включая представления на базе классов, эскизов или расширений, таких как Flask-Via.
Прежде всего, вам нужно будет создать каталог для проекта. Откройте терминал и запустите следующую команду:
- mkdir flask_request_example
Затем перейдите в новый каталог:
- cd flask_request_example
Затем установите Flask. Откройте терминал и запустите следующую команду:
- pipenv install Flask
Команда pipenv
создаст среду virtualenv для этого проекта, Pipfile, install flask
и Pipfile.lock.
Для активации virtualenv этого проекта запустите следующую команду:
- pipenv shell
Чтобы получить доступ к входящим данным в Flask, вам нужно будет использовать объект request
. В объекте request
хранятся все входящие данные запроса, включая тип MIME, источник, IP-адрес, необработанные данные, метод HTTP, заголовки и т. д.
Хотя вся информация в объекте request
может быть полезной для наших целей, в этом учебном модуле мы уделим основное внимание данным, которые обычно предоставляются вызывающей стороной напрямую.
Чтобы получить доступ к запрашиваемому объекту в Flask, вам потребуется импортировать его из библиотеки Flask:
from flask import request
После этого у вас появится возможность использовать его в любых ваших функциях представлений.
Используйте редактор кода для создания файла app.py
. Импортируйте Flask
и объект request
. Также установите маршруты для query-example
, form-example
и json-example
:
# import main Flask class and request object
from flask import Flask, request
# create the Flask app
app = Flask(__name__)
@app.route('/query-example')
def query_example():
return 'Query String Example'
@app.route('/form-example')
def form_example():
return 'Form Data Example'
@app.route('/json-example')
def json_example():
return 'JSON Object Example'
if __name__ == '__main__':
# run app in debug mode on port 5000
app.run(debug=True, port=5000)
Затем откройте терминал и запустите приложение с помощью следующей команды:
- python app.py
Приложение будет запущено на порту 5000, чтобы вы могли просмотреть каждый маршрут в браузере, используя следующие ссылки:
http://127.0.0.1:5000/query-example (or localhost:5000/query-example)
http://127.0.0.1:5000/form-example (or localhost:5000/form-example)
http://127.0.0.1:5000/json-example (or localhost:5000/json-example)
Код устанавливает три маршрута, и при открытии каждого маршрута вы увидите сообщения "Query String Example"
, "Form Data Example"
и "JSON Object Example"
.
Аргументы URL, добавляемые в строку запроса, часто используются для передачи данных в веб-приложение. Возможно, вам уже приходилось видеть строку запроса на веб-страницах.
Строка запроса выглядит следующим образом:
example.com?arg1=value1&arg2=value2
Строка запроса начинается после знака (?
) вопроса:
example.com?arg1=value1&arg2=value2
В ней содержатся пары ключ-значение, разделенные символом амперсанда (&
):
example.com?arg1=value1&arg2=value2
В каждой паре после ключа идет знак равенства (=
), а затем идет значение.
arg1 : value1
arg2 : value2
Строки запросов полезны для передачи данных, которые не требуют действий со стороны пользователя. Вы можете сгенерировать строку запроса в своем приложении и добавить ее к URL так, чтобы при запросе пользователя данные передавались автоматически. Строка запроса также может быть сгенерирована формами, использующими метод GET.
Давайте добавим строку запроса в маршрут query-example
. В этом гипотетическом примере, мы укажем имя языка программирования, которое будет отображаться на экране. Создайте ключ "language"
и значение "Python"
:
http://127.0.0.1:5000/query-example?language=Python
Если вы запустите приложение и перейдете к этому URL, вы увидите сообщение "Query String Example"
.
Вам нужно будет программировать часть, обрабатывающую аргументы запроса. Этот код считает ключ language
, используя request.args.get('language')
или request.args['language']
.
При вызове request.args.get('language')
приложение продолжит работу, если ключ language
отсутствует по указанному URL. В этом случае данный метод будет иметь результат None
.
При вызове request.args['language']
приложение возвращает ошибку 400, если ключ language
отсутствует по указанному URL.
При работе со строками запросов, рекомендуется использовать request.args.get()
, чтобы предотвратить возможные сбои в работе приложения.
Давайте прочитаем ключ language
и выведем его.
Измените маршрут query-example
в app.py
с помощью следующего кода:
@app.route('/query-example')
def query_example():
# if key doesn't exist, returns None
language = request.args.get('language')
return '''<h1>The language value is: {}</h1>'''.format(language)
Затем запустите приложение и перейдите к URL:
http://127.0.0.1:5000/query-example?language=Python
Браузер должен вывести следующее сообщение:
OutputThe language value is: Python
Аргумент из URL привязывается к переменной language
, а затем возвращается через браузер.
Чтобы добавить дополнительные параметры запроса, вы можете добавить амперсанды и новые пары ключ-значение в конце URL. Создайте ключ "framework"
и значение "Flask"
:
http://127.0.0.1:5000/query-example?language=Python&framework=Flask
Если вам нужно больше, продолжайте добавлять амперсанды и пары ключ-значение. Создайте ключ "website"
и значение "DigitalOcean"
:
http://127.0.0.1:5000/query-example?language=Python&framework=Flask&website=DigitalOcean
Чтобы получить доступ к этим значениям, мы все равно используем request.args.get()
или request.args[]
. Давайте используем оба варианта, чтобы продемонстрировать, что произойдет при отсутствии ключа. Измените маршрут query_example
, чтобы назначить значение результатов переменным и вывести их:
@app.route('/query-example')
def query_example():
# if key doesn't exist, returns None
language = request.args.get('language')
# if key doesn't exist, returns a 400, bad request error
framework = request.args['framework']
# if key doesn't exist, returns None
website = request.args.get('website')
return '''
<h1>The language value is: {}</h1>
<h1>The framework value is: {}</h1>
<h1>The website value is: {}'''.format(language, framework, website)
Затем запустите приложение и перейдите к URL:
http://127.0.0.1:5000/query-example?language=Python&framework=Flask&website=DigitalOcean
Браузер должен вывести следующее сообщение:
OutputThe language value is: Python
The framework value is: Flask
The website value is: DigitalOcean
Удалите ключ language
из URL:
http://127.0.0.1:5000/query-example?framework=Flask&website=DigitalOcean
Браузер должен вывести следующее сообщение со словом None
, если для language
будет отсутствовать значение:
OutputThe language value is: None
The framework value is: Flask
The website value is: DigitalOcean
Удалите ключ framework
из URL:
http://127.0.0.1:5000/query-example?language=Python&website=DigitalOcean
Браузер должен вывести сообщение об ошибке, потому что он ожидает получить значение framework
:
Outputwerkzeug.exceptions.BadRequestKeyError
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'framework'
Теперь вы должны понимать, как следует обрабатывать строки запросов. Перейдем к следующему типу входящих данных.
Данные форм поступают из форм, отправленных на маршрут в виде запроса POST. Вместо отображения данных в URL (кроме случаев отправки форм в виде запроса GET) данные форм передаются приложению незаметно. Хотя вы не видите передаваемые данные форм, ваше приложение может их считывать.
Чтобы продемонстрировать это, давайте изменим маршрут form-example
в app.py
так, чтобы принимать запросы GET и POST и возвращать форму:
# allow both GET and POST requests
@app.route('/form-example', methods=['GET', 'POST'])
def form_example():
return '''
<form method="POST">
<div><label>Language: <input type="text" name="language"></label></div>
<div><label>Framework: <input type="text" name="framework"></label></div>
<input type="submit" value="Submit">
</form>'''
Затем запустите приложение и перейдите к URL:
http://127.0.0.1:5000/form-example
Браузер должен отображать форму с двумя полями ввода: одно language
и одно для framework
, а также кнопку отправки.
Важнее всего знать об этой форме то, что она выполняет запрос POST к тому же маршруту, который сгенерировал форму. Все ключи, которые считываются в приложении, поступают от атрибутов name
в полях ввода формы. В этом случае language
и framework
являются именами полей ввода, и поэтому у вас будет доступ к ним в приложении.
Внутри функции просмотра вам нужно будет проверить метод запроса: GET или POST. Если это запрос GET, вы можете вывести форму. В противном случае это запрос POST, и вам нужно обработать входящие данные.
Измените маршрут form-example
в app.py
, добавив следующий код:
# allow both GET and POST requests
@app.route('/form-example', methods=['GET', 'POST'])
def form_example():
# handle the POST request
if request.method == 'POST':
language = request.form.get('language')
framework = request.form.get('framework')
return '''
<h1>The language value is: {}</h1>
<h1>The framework value is: {}</h1>'''.format(language, framework)
# otherwise handle the GET request
return '''
<form method="POST">
<div><label>Language: <input type="text" name="language"></label></div>
<div><label>Framework: <input type="text" name="framework"></label></div>
<input type="submit" value="Submit">
</form>'''
Затем запустите приложение и перейдите к URL:
http://127.0.0.1:5000/form-example
Введите в поле language
значение Python
, а в поле framework
— значение Flask
. Затем нажмите кнопку Submit.
Браузер должен вывести следующее сообщение:
OutputThe language value is: Python
The framework value is: Flask
Теперь вы понимаете, как обрабатывать данные формы. Перейдем к следующему типу входящих данных.
Данные JSON обычно создаются процессом, который вызывает маршрут.
Пример объекта JSON:
{
"language": "Python",
"framework": "Flask",
"website": "Scotch",
"version_info": {
"python": "3.9.0",
"flask": "1.1.2"
},
"examples": ["query", "form", "json"],
"boolean_test": true
}
Такая структура позволяет передавать более сложные данные, чем строки запросов и данные форм. В этом примере вы видите вложенные объекты JSON и массив элементов. Этот формат данных может обрабатываться Flask.
Измените маршрут form-example
в app.py
, чтобы принимать запросы POST и игнорировать другие запросы, в частности GET:
@app.route('/json-example', methods=['POST'])
def json_example():
return 'JSON Object Example'
Для строк запросов и данных форм в этом учебном модуле мы использовали браузер, но для отправки объекта JSON мы используем Postman, чтобы отправлять персонализированные запросы в URL.
Примечание. Если вам нужна помощь в навигации по интерфейсу Postman для отправки запросов, воспользуйтесь официальной документацией.
Добавьте URL в Postman и измените тип на POST. На вкладке body переключитесь на raw и выберите JSON из раскрывающегося списка.
Эти настройки необходимы, чтобы Postman мог правильно отправлять данные JSON и чтобы ваше приложение Flask понимало, что получает данные JSON:
POST http://127.0.0.1:5000/json-example
Body
raw JSON
Затем скопируйте в поле ввода текста предыдущий пример JSON.
Отправьте запрос. Вы должны получить ответ "JSON Object Example"
. Это не так интересно, но это ожидаемо, потому что код для обработки ответа данных JSON еще нужно написать.
Чтобы читать данные, вам нужно понимать, как Flask преобразует данные JSON в структуры данных Python:
{"key" : "value"}
в JSON соответствуют somedict['key']
, который возвращает значение в Python.[1,2,3,4,5]
true
и false
становятся True
и False
в Python.Теперь давайте поработаем с кодом, чтобы считывать входящие данные JSON.
Вначале добавим все содержимое объекта JSON в переменную, используя request.get_json()
.
request.get_json()
конвертирует объект JSON в данные Python. Давайте назначим данные входящего запроса в переменные и выведем их, внеся следующие изменения в маршрут json-example
:
# GET requests will be blocked
@app.route('/json-example', methods=['POST'])
def json_example():
request_data = request.get_json()
language = request_data['language']
framework = request_data['framework']
# two keys are needed because of the nested object
python_version = request_data['version_info']['python']
# an index is needed because of the array
example = request_data['examples'][0]
boolean_test = request_data['boolean_test']
return '''
The language value is: {}
The framework value is: {}
The Python version is: {}
The item at index 0 in the example list is: {}
The boolean value is: {}'''.format(language, framework, python_version, example, boolean_test)
Обратите внимание на процедуру доступа к элементам, находящимся не на верхнем уровне. Поскольку мы вводим вложенный объект, используется ['version']['python']
. А ['examples'][0]
используется для доступа к индексу 0 в массиве example.
Если объект JSON, отправленный с запросом, не имеет ключа, доступ к которому осуществляется через функцию view, запрос не будет выполняться. Если вы не хотите, чтобы запрос выдавал сбой при отсутствии ключа, вам нужно будет проверить наличие ключа, прежде чем пытаться получить к нему доступ.
# GET requests will be blocked
@app.route('/json-example', methods=['POST'])
def json_example():
request_data = request.get_json()
language = None
framework = None
python_version = None
example = None
boolean_test = None
if request_data:
if 'language' in request_data:
language = request_data['language']
if 'framework' in request_data:
framework = request_data['framework']
if 'version_info' in request_data:
if 'python' in request_data['version_info']:
python_version = request_data['version_info']['python']
if 'examples' in request_data:
if (type(request_data['examples']) == list) and (len(request_data['examples']) > 0):
example = request_data['examples'][0]
if 'boolean_test' in request_data:
boolean_test = request_data['boolean_test']
return '''
The language value is: {}
The framework value is: {}
The Python version is: {}
The item at index 0 in the example list is: {}
The boolean value is: {}'''.format(language, framework, python_version, example, boolean_test)
Запустите приложение и отправьте пример запроса JSON с помощью Postman. В ответе вы увидите следующее:
OutputThe language value is: Python
The framework value is: Flask
The Python version is: 3.9
The item at index 0 in the example list is: query
The boolean value is: false
Теперь вы должны понимать принципы обработки объектов JSON.
В этом учебном модуле мы создали приложение Flask с тремя маршрутами, которое будет принимать строки запросов, данные форм и объекты JSON.
Также не забывайте, что все подходы должны учитывать постоянную возможность ошибки при отсутствии ключа.
Предупреждение. В этом учебном модуле мы не рассмотрели вопрос санитарной обработки пользовательского ввода. Санитарная обработка пользовательского ввода делает так, чтобы приложение не могло неожиданно прекращать работу или обходить меры безопасности.
Если вы хотите узнать больше о Flask, на нашей странице тем по Flask вы найдете полезные упражнения и проекты по программированию.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.