Как получить данные с формы flask
Перейти к содержимому

Как получить данные с формы flask

  • автор:

#11 Работа с формами во Flask

Формы — важный элемент любого веб-приложения, но, к сожалению, работать с ними достаточно сложно. Сначала нужно подтвердить данные на стороне клиента, затем — на сервере. И даже этого недостаточно, если разработчик приложения озабочен такими проблемами безопасности как CSRF, XSS, SQL Injection и так далее. Все вместе — это масса работы. К счастью, есть отличная библиотека WTForms, выполняет большую часть задач за разработчика. Перед тем как узнать больше о WTForms, следует все-таки разобраться, как работать с формами без библиотек и пакетов.

Работа с формами — сложный вариант

Для начала создадим шаблон login.html со следующим кодом:

 html lang="en"> head> meta charset="UTF-8"> title>Logintitle> head> body> if message %> p>message >>p> endif %> form action="" method="post"> p> label for="username">Usernamelabel> input type="text" name="username"> p> p> label for="password">Passwordlabel> input type="password" name="password"> p> p> input type="submit"> p> form> body> html> 

Этот код нужно добавить после функции представления books() в файле main2.py :

from flask import Flask, render_template, request #. @app.route('/login/', methods=['post', 'get']) def login(): message = '' if request.method == 'POST': username = request.form.get('username') # запрос к данным формы password = request.form.get('password') if username == 'root' and password == 'pass': message = "Correct username and password" else: message = "Wrong username or password" return render_template('login.html', message=message) #. 

Стоит обратить внимание, что аргумент methods передан декоратору route() . По умолчанию обработчик запросов вызывается только в тех случаях, когда метод request.method — GET или HEAD. Это можно изменить, передав список разрешенных HTTP-методов аргументу-ключевому слову methods . С этого момента функция представления login будет вызываться только тогда, когда запрос к /login/ будет сделан с помощью методов GET, POST или HEAD. Если попробовать получить доступ к URL /login/ другим методом, появится ошибка HTTP 405 Method Not Allowed.

В прошлых уроках обсуждалось то, что объект request предоставляет информацию о текущем веб-запросе. Информация, полученная с помощью формы, хранится в атрибуте form объекта request . request.form — это неизменяемый объект типа словарь, известный как ImmutableMultiDict .

Дальше нужно запустить сервер и зайти на https://localhost:5000/login/ . Откроется такая форма.

форма во Flask

Запрос к странице был сделан с помощью метода GET, поэтому код внутри блока if функции login() пропущен.

Если попробовать отправить форму без ввода данных, страница будет выглядеть следующим образом:

ошибка в форме во Flask

В этот раз страница была отправлена методом POST, поэтому код внутри if оказался исполнен. Внутри этого блока приложение принимает имя пользователя и пароль и устанавливает сообщение для message . Поскольку форма оказалась пустой, отобразилось сообщение об ошибке.

Если заполнить форму с корректными именем пользователям и паролем и нажать Enter, появится приветственное сообщение “Correct username and password” :

Заполненная форма во Flask

Таким образом можно работать с формами во Flask. Теперь же стоит обратить внимание на пакет WTForms.

WTForms

WTForms – это мощная библиотека, написанная на Python и независимая от фреймворков. Она умеет генерировать формы, проверять их и предварительно заполнять информацией (удобно для редактирования) и многое другое. Также она предлагает защиту от CSRF. Для установки WTForms используется Flask-WTF.

Flask- WTF – это расширение для Flask, которое интегрирует WTForms во Flask. Оно также предлагает дополнительные функции, такие как загрузка файлов, reCAPTCHA, интернационализация (i18n) и другие. Для установки Flask-WTF нужно ввести следующую команду.

(env) gvido@vm:~/flask_app$ pip install flask-wtf 

Создание класса Form

Начать стоит с определения форм в виде классов Python. Каждая форма должна расширять класс FlaskForm из пакета flask_wtf . FlaskForm — это обертка, содержащая полезные методы для оригинального класса wtform.Form , который является основной для создания форм. Внутри класса формы, поля формы определяются в виде переменных класса. Поля формы определяются путем создания объекта, ассоциируемого с типом поля. Пакет wtform предлагает несколько классов, представляющих собой следующие поля: StringField , PasswordField , SelectField , TextAreaField , SubmitField и другие.

Для начала нужно создать файл forms.py внутри словаря flask_app и добавить в него следующий код.

from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, TextAreaField from wtforms.validators import DataRequired, Email class ContactForm(FlaskForm): name = StringField("Name: ", validators=[DataRequired()]) email = StringField("Email: ", validators=[Email()]) message = TextAreaField("Message", validators=[DataRequired()]) submit = SubmitField("Submit") 

Здесь определен класс формы ContactForm с четырьмя полями: name , email , message и sumbit . Эти переменные будут использоваться, чтобы отрендерить поля формы, а также назначать и получать информацию из них. Эта форма создана с помощью двух StringField , TextAreaField и SumbitField . Каждый раз когда создается объект поля, определенные аргументы передаются его функции-конструктору. Первый аргумент — строка, содержащая метку, которая будет отображаться внутри тега в тот момент, когда поле отрендерится. Второй опциональный аргумент — список валидаторов (элементов системы проверки), которые передаются конструктору в виде аргументов-ключевых слов. Валидаторы — это функции или классы, которые определяют, корректна ли введенная в поле информация. Для каждого поля можно использовать несколько валидаторов, разделив их запятыми ( , ). Модуль wtforms.validators предлагает базовые валидаторы, но их можно создавать самостоятельно. В этой форме используются два встроенных валидатора: DataRequired и Email .

DataRequired: он проверяет, ввел ли пользователь хоть какую-информацию в поле.

Email: проверяет, является ли введенный электронный адрес действующим.

Введенные данные не будут приняты до тех пор, пока валидатор не подтвердит соответствие данных.

Примечание: это лишь основа полей форм и валидаторов. Полный список доступен по ссылке https://wtforms.readthedocs.io.

Установка SECRET_KEY

По умолчанию Flask-WTF предотвращает любые варианты CSFR-атак. Это делается с помощью встраивания специального токена в скрытый элемент внутри формы. Затем этот токен используется для проверки подлинности запроса. До того как Flask-WTF сможет сгенерировать csrf-токен, необходимо добавить секретный ключ. Установить его в файле main2.py необходимо следующим образом:

#. app.debug = True app.config['SECRET_KEY'] = 'a really really really really long secret key' manager = Manager(app) #. 

Здесь используется атрибут config объекта Flask . Атрибут config работает как словарь и используется для размещения параметров настройки Flask и расширений Flask, но их можно добавлять и самостоятельно.

Секретный ключ должен быть строкой — такой, которую сложно разгадать и, желательно, длинной. SECRET_KEY используется не только для создания CSFR-токенов. Он применяется и в других расширениях Flask. Секретный ключ должен быть безопасно сохранен. Вместо того чтобы хранить его в приложении, лучше разместить в переменной окружения. О том как это сделать — будет рассказано в следующих разделах.

Формы в консоли

Откроем оболочку Python с помощью следующей команды:

(env) gvido@vm:~/flask_app$ python main2.py shell 

Это запустит оболочку Python внутри контекста приложения.

Теперь нужно импортировать класс ContactForm и создать экземпляр объекта новой формы, передав данные формы.

>>> >>> from forms import ContactForm >>> from werkzeug.datastructures import MultiDict >>> >>> >>> form1 = ContactForm(MultiDict([('name', 'jerry'),('email', 'jerry@mail.com')])) >>> 

Стоит обратить внимание, что данные передаются в виде объекта MultiDict , потому что функция-конструктор класса wtforms.Form принимает аргумент типа MutiDict . Если данные формы не определены при создании экземпляра объекта формы, а форма отправлена с помощью запроса POST, wtforms.Form использует данные из атрибута request.form . Стоит вспомнить, что request.form возвращает объект типа ImmutableMultiDict . Это то же самое, что и MultiDict , но он неизменяемый.

Метод validate() проверяет форму. Если проверка прошла успешно, он возвращает True , если нет — False .

>>> >>> form1.validate() False >>> 

Форма не прошла проверку, потому что обязательному полю message при создании объекта формы не было передано никаких данных. Получить доступ к ошибкам форм можно с помощью атрибута errors объекта формы:

>>> >>> form1.errors 'message': ['This field is required.'], 'csrf_token': ['The CSRF token is missing.']> >>> 

Нужно обратить внимание, что в дополнение к сообщению об ошибке для поля message , вывод также содержит сообщение об ошибке о недостающем csfr-токене. Это из-за того что в данных формы нет запроса POST с csfr-токеном.

Отключить CSFR-защиту можно, передав csfr_enabled=False при создании экземпляра класса формы. Пример:

>>> form3 = ContactForm(MultiDict([('name', 'spike'),('email', 'spike@mail.com')]), csrf_enabled=False) >>> >>> form3.validate() False >>> >>> form3.errors 'message': ['This field is required.']> >>> >>> 

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

>>> >>> form4 = ContactForm(MultiDict([('name', 'jerry'), ('email', 'jerry@mail.com'), ('message', "hello tom")]), csrf_enabled=False) >>> >>> form4.validate() True >>> >>> form4.errors > >>> 

Проверка формы в этот раз прошла успешно.

Следующий шаг — рендеринг формы.

Рендеринг формы

Существует два варианта рендеринга:

  1. Один за одним.
  2. С помощью цикла

Рендеринг полей один за одним

Поскольку в шаблонах есть доступ к экземпляру формы, можно использовать имена полей, чтобы отрендерить имена, метки и ошибки:

 form.field_name.label() >> form.field_name() >> for error in form.field_name.errors %> error >> endfor %> 

Стоит протестировать этот способ в консоли:

>>> >>> from forms import ContactForm >>> from jinja2 import Template >>> >>> form = ContactForm() >>> 

Здесь экземпляр объекта формы был создан без данных запроса. Так и происходит, когда форма отображается первый раз с помощью запроса GET.

>>> >>> >>> Template(">").render(form=form) ' ' >>> >>> Template(">").render(form=form) '' >>> >>> >>> Template(">").render(form=form) ' ' >>> >>> Template(">").render(form=form) '' >>> >>> >>> Template(">").render(form=form) '' >>> >>> Template(">").render(form=form) ' ' >>> >>> >>> Template(">").render(form=form) '' >>> >>> 

Поскольку форма выводится первый раз, у полей не будет ошибок проверки. Следующий код наглядно демонстрирует это:

>>> >>> >>> Template(">").render(form=form) '' >>> >>> >>> Template(">").render(form=form) '' >>> >>> >>> Template(">").render(form=form) '' >>> >>> 

Вместо отображения ошибок проверки для каждого поля можно использовать form.errors , чтобы получить доступ к ошибкам валидации, относящимся к форме. forms.errors используется чтобы отображать ошибки проверки в верхней части формы.

>>> >>> Template(">").render(form=form) '' >>> 

При рендеринге полей и меток можно добавить дополнительные аргументы-ключевые слова, которые окажутся в HTML-коде в виде пар ключей-значений. Например:

>>> >>> Template('>').render(form=form) '' >>> >>> >>> Template('>').render(form=form) ' ' >>> >>> 

Предположим, форма была отправлена. Теперь можно попробовать отрендерить поля и посмотреть, что получится.

>>> >>> from werkzeug.datastructures import MultiDict >>> >>> form = ContactForm(MultiDict([('name', 'spike'),('email', 'spike@mail.com')])) >>> >>> form.validate() False >>> >>> >>> Template(">").render(form=form) '' >>> >>> >>> Template(">").render(form=form) '' >>> >>> >>> Template(">").render(form=form) ' ' >>> >>> 

Стоит обратить внимание, что у атрибута value в полях name и email есть данные. Но элемент для поля message пуст, потому что ему данные переданы не были. Получить доступ к ошибке валидации для поля message можно следующим образом:

>>> >>> Template(">").render(form=form) 'This field is required.' >>> 

Как вариант, form.errors можно использовать, чтобы перебрать все ошибки валидации за раз.

Стоит обратить внимание, что ошибки csfr-токена нет, потому что запрос был отправлен без токена. Отрендерить поле csfr можно как и любое другое поле:

>>> >>> Template(">").render(form=form) '' >>> 

Рендеринг полей один из одним может занять много времени, особенно если их несколько. Для таких случаев используется цикл.

Рендеринг полей с помощью цикла

Следующий код демонстрирует, как можно отрендерить поля с помощью цикла for.

>>> >>> s = """\ . 
. > .
. .
. > . > . .
>
. .
. . """
>>> >>> >>> print(Template(s).render(form=form)) div> input id="csrf_token" name="csrf_token" type="hidden" value="IjZjOTBkOWM4ZmQ0MGMzZTY3NDc3ZTNiZDIxZTFjNDAzMGU1YzEwOTYi.DQlFlA.GQ-PrxsCJkQfoJ5k6i5YfZMzC7k"> /div> div> label for="name">Name: /label> input id="name" name="name" type="text" value="spike"> /div> div> label for="email">Email: /label> input id="email" name="email" type="text" value="spike@mail.com"> /div> div> label for="message">Message/label> textarea id="message" name="message">/textarea> div class="error">This field is required./div> /div> div> label for="submit">Submit/label> input id="submit" name="submit" type="submit" value="Submit"> /div> >>> >>>

Важно заметить, что вне зависимости от используемого метода нужно вручную добавлять тег , чтобы обернуть поля формы.

Теперь, зная как создавать, поверять и рендерить формы, можно использовать полученные знания для создания реальных форм.

Вначале нужно создать шаблон contact.html со следующим кодом:

 html lang="en"> head> meta charset="UTF-8"> title>Titletitle> head> body> form action="" method="post"> form.csrf_token() >> for field in form if field.name != "csrf_token" %> p>field.label() >>p> p>field >> for error in field.errors %> error >> endfor %> p> endfor %> form> body> html> 

Единственный недостающий кусочек пазла — функция представления, которая будет создана далее.

Работа с подтверждением формы

Откроем main2.py , чтобы добавить следующий код после функции представления login() .

from flask import Flask, render_template, request, redirect, url_for from flask_script import Manager, Command, Shell from forms import ContactForm #. @app.route('/contact/', methods=['get', 'post']) def contact(): form = ContactForm() if form.validate_on_submit(): name = form.name.data email = form.email.data message = form.message.data print(name) print(email) print(message) # здесь логика базы данных print("\nData received. Now redirecting . ") return redirect(url_for('contact')) return render_template('contact.html', form=form) #. 

В 7 строке создается объект формы. На 8 строке проверяется значение, которое вернул метод validate_on_submit() для исполнения кода внутри инструкции if.

Почему используется validate_on_sumbit() , а не validate() , как это было в консоли?

validate() всего лишь проверяет, корректны ли данные формы. Он не проверяет, был ли запрос отправлен с помощью метода POST. Это значит, что если использовать метод validate() , тогда запрос GET к /contact/ запустит форму проверки, а пользователь увидит ошибки валидации. Вообще процедура проверки запускается только в том случае, если данные были отправлены с помощью метода POST. В противном случае вернется False . Метод validate_on_submit() вызывает метод validate() внутри себя. Также нужно обратить внимание, что при создании экземпляра объекта формы данные не передаются, потому что когда форма отправляется с помощью запроса POST, WTForm считывает данные формы из атрибута request.form .

Поля формы, определенные в классе формы становятся атрибутами объекта формы. Чтобы получить доступ к данным поля используется атрибут data поля формы:

form.name.data # доступ к данным в поле name. form.email.data # доступ к данным в поле email. 

Чтобы получить доступ ко всем данные формы сразу нужно использовать атрибут data к объекту формы:

form.data # доступ ко всем данным 

Если использовать запрос GET при посещении /contact/ , метод validate_on_sumbit() вернет False . Код внутри if будет пропущен, а пользователь получит пустую HTML-форму.

Когда форма отправляется с помощью запроса POST, validate_on_sumbit() возвращает True , предполагая, что данные верны. Вызовы print() внутри блока if выведут данные, введенные пользователем, а функция redirect() перенаправит пользователя на страницу /contact/ . С другой стороны, если validate_on_sumbit() вернет False , исполнение инструкций внутри тела if будет пропущено, и появится сообщение об ошибке валидации.

Если сервер не запущен, его нужно запустить и открыть https://localhost:5000/contact/ . Появится следующая контактная форма:

контактная форма во Flask

Если попробовать нажать Submit, не вводя данных, появятся следующие сообщения об ошибках валидации:

ошибка валидации формы во Flask

ошибка валидации email во Flask

Теперь можно ввести определенные данные в поля Name и Message и некорректные данные в поле Email, и попробовать отправить форму снова.

Нужно обратить внимание, что все поля содержат данные из прошлого запроса.

Теперь можно ввести корректный email в поле Email и нажать Submit. Теперь проверка пройдет успешно, а в оболочке появится следующий вывод:

Spike spike@gmail.com A Message Data received. Now redirecting . 

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

Рекомендуется отображать обратную связь пользователю после успешной отправки. Во Flask это делается с помощью всплывающих сообщений.

Всплывающие сообщения

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

Для отображения сообщения используется функция flash() из пакета flask . Функция flash() принимает два аргумента: сообщение и категория (опционально). Категория указывает на тип сообщения: _success_ , _error_ , _warning_ и так далее. Категория может быть использована в шаблоне, чтобы определить тип сообщения.

Снова откроем main2.py , чтобы добавить flash(“Message Received”, “success”) прямо перед вызовом redirect() в функции представления contact() :

from flask import Flask, render_template, request, redirect, url_for, flash #. # здесь логика базы данных print("\nData received. Now redirecting . ") flash("Message Received", "success") return redirect(url_for('contact')) return render_template('contact.html', form=form) 

Сообщение, заданное с помощью функции flash() , будет доступно только последующему запросу, а потом удалится.

Это только настройка сообщения. Для его отображения нужно поменять также шаблон.

Для этого нужно открыть файл contact.html и изменить его следующим образом:

Jinja предлагает функцию get_flashed_messages() , которая возвращает список активных сообщений без категории. Чтобы получить их вместе с категорией нужно передать with_category=True при вызове get_flashed_messages() . Когда значение with_categories – True , get_flashed_messages() вернет список кортежей формы (category, message) .

После этих изменений следует открыть https://localhost:5000/contact снова. Заполнить форму и нажать Submit . Сообщение об успешной отправке отобразится в верхней части формы.

Успешная отправка формы во Flask

  • ТЕГИ
  • Flask
  • Уроки по Flask на русском

Как получить данные из input и перенести их в код Flask?

Мне нужно получить данные из поля input в HTML в код Flask для дальнейшей работы с ними. Я подключил модуль request , но получить данные все равно не удается. На странице ошибка 400 Bad Request . Можно ли ее как-то решить? HTML-код:

    >" /> Регистрация  

Регистрация

@app.route('/reg', methods=['POST', 'GET']) def reg(): return render_template("reg.html") @app.route('/reg_run', methods=['POST', 'GET']) def reg_run(): a = request.form['name'] print(a) return a 

Отслеживать
задан 24 апр 2021 в 10:08
Nikita2431 Nikita2431
35 6 6 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Скажите, пожалуйста, это вот так вы хотите отправить форму?

 Подтяните, пожалуйста, основы HTML. Это просто ссылка, которая генерирует GET-запрос по указанному URL. Ну а результат предсказуемый, в обработчик не присылается вообще ничего, он падает с ошибкой и возвращает код 400.

Должно сработать вот так:

В этом случае действительно будет отправляться POST-запрос с телом, в котором будут поля формы, которые потом можно будет получить и обработать.

И не забывайте закрывать тэги, косая черта обязательно нужна, даже если и без нее как бы работает.

Получение данных из запроса в Flask

Разработчики, работающие с Flask, часто сталкиваются со следующей задачей: необходимо обработать данные, отправленные на сервер через HTTP-запрос. Однако, при попытке получить доступ к этим данным через request.data , они обнаруживают, что это поле пустое.

from flask import request @app.route('/', methods=['GET', 'POST']) def parse_request(): data = request.data # data is empty # need posted data here

Так происходит из-за того, что request.data возвращает пустую строку, если данные не были отправлены как форма или не были представлены в виде JSON.

Чтобы получить доступ к данным, отправленным через POST-запрос, можно использовать request.get_json() для JSON-данных или request.form для данных формы.

В случае с JSON-данными код может выглядеть следующим образом:

from flask import request @app.route('/', methods=['POST']) def parse_request(): data = request.get_json() # data is dictionary with json data

Или, в случае с данными формы:

from flask import request @app.route('/', methods=['POST']) def parse_request(): data = request.form # data is dictionary with form data

Таким образом, с помощью request.get_json() и request.form можно получить доступ к данным, отправленным на сервер через HTTP-запрос, в формате JSON или в виде формы соответственно.

Обработка данных входящих запросов в Flask

Обработка данных входящих запросов в Flask

Веб-приложениям часто требуется обрабатывать данные входящих запросов пользователей. Эта полезная нагрузка может иметь форму строк запросов, данных форм и объектов JSON. Flask, как и любая другая веб-инфраструктура, предоставляет доступ к данным запросов.

В этом учебном модуле мы создадим приложение Flask с тремя маршрутами, которое будет принимать строки запросов, данные форм и объекты JSON.

Предварительные требования

Для данного обучающего руководства вам потребуется следующее:

  • Для данного проекта потребуется установить Python в локальной среде.
  • В этом проекте мы будем использовать инструмент Pipenv, предоставляющий отличные возможности упаковки для программирования на Python. Он предоставляет возможности Pipfile, pip и virtualenv в одной команде.
  • Для тестирования конечных точек API потребуется установить Postman или другой подобный инструмент.

Для этого учебного модуля мы использовали версии Pipenv v2020.11.15, Python v3.9.0 и Flask v1.1.2.

Настройка проекта

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

Прежде всего, вам нужно будет создать каталог для проекта. Откройте терминал и запустите следующую команду:

Затем перейдите в новый каталог:

Затем установите Flask. Откройте терминал и запустите следующую команду:

Команда pipenv создаст среду virtualenv для этого проекта, Pipfile, install flask и Pipfile.lock.

Для активации virtualenv этого проекта запустите следующую команду:

Чтобы получить доступ к входящим данным в 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) 

Затем откройте терминал и запустите приложение с помощью следующей команды:

Приложение будет запущено на порту 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 '''

The language value is: <>

'''
.format(language)

Затем запустите приложение и перейдите к URL:

http://127.0.0.1:5000/query-example?language=Python 

Браузер должен вывести следующее сообщение:

Output
The 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 '''  

The language value is: <>

The framework value is: <>

The website value is: <>'''.format(language, framework, website)

Затем запустите приложение и перейдите к URL:

http://127.0.0.1:5000/query-example?language=Python&framework=Flask&website=DigitalOcean 

Браузер должен вывести следующее сообщение:

Output
The 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 будет отсутствовать значение:

Output
The 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 :

Output
werkzeug.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"> 
Language:
Framework:
'''

Затем запустите приложение и перейдите к 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 '''  

The language value is: <>

The framework value is: <>

'''
.format(language, framework)
# otherwise handle the GET request return '''
Language:
Framework:
'''

Затем запустите приложение и перейдите к URL:

http://127.0.0.1:5000/form-example 

Введите в поле language значение Python , а в поле framework — значение Flask . Затем нажмите кнопку Submit.

Браузер должен вывести следующее сообщение:

Output
The language value is: Python The framework value is: Flask

Теперь вы понимаете, как обрабатывать данные формы. Перейдем к следующему типу входящих данных.

Использование данных JSON

Данные 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:

  • Все объекты конвертируются в словари Python. в JSON соответствуют somedict[‘key’] , который возвращает значение в Python.
  • Массив в JSON конвертируется в список в Python. Поскольку синтаксис одинаковый, приведем список примеров: [1,2,3,4,5]
  • Значения в кавычках объекта JSON станут строками в Python.
  • Логические операторы true и false становятся True и False в Python.
  • Числа без кавычек становятся числами в 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. В ответе вы увидите следующее:

Output
The 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.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *