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

Любое веб-приложение содержит такой важный элемент, как формы. К сожалению, не всегда с ними просто работать. Логика взаимодействия с формами для новичка довольно непростая. Ведь сперва необходимо подтвердить данные на стороне клиента, а потом – на сервере. И даже этого недостаточно, если разработчику нужно сделать этот обмен данными безопасным. В совокупности даже опытному программисту нужно немало работать. К счастью, можно воспользоваться библиотекой WTForms, которая позволяет без библиотек и пакетов работать с формами.

Работа с формами – непростой метод

Сперва давайте создадим шаблон login.html, в котором будет содержаться следующий код. 

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>Login</title>

</head>

<body>




    {% if message %}

        <p>{{ message }}</p>

    {% endif %}

    

    <form action="" method="post">

        <p>

    <label for="username">Username</label>

    <input type="text" name="username">

</p>

<p>

    <label for="password">Password</label>

    <input type="password" name="password">

</p>

<p>

    <input type="submit">

</p>

    </form>

    

</body>

</html>

А после функции представления books необходимо добавить этот код. 

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. Если же использовать другие методы, то появится ошибка HTTP 405 Method Not Allowed.

Объект класса request позволяет получить данные о текущем веб-запросе. Данные, полученные с использованием формы, находятся в атрибуте form объекта request. Это словарь, который нельзя редактировать и имеющий название ImmutableMutiDict.

После этого осуществляется переход по адресу https://localhost:5000/login/. Далее открывается форма.Работа с формами во Flask

Далее, для получения доступа к странице будет использоваться метод GET. Следовательно, код, находящийся внутри if-блока функции login() не будет учитываться в ходе исполнения приложения.

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

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

Если использовать правильное имя пользователя и пароль при заполнении формы и нажать Enter, то тогда появится соответствующее уведомление над формой.Работа с формами во Flask

Вот, как осуществляется работа с формами во Flask. Но также необходимо обратить внимание на пакет WTForms.

Что такое WTForms?

Это специальная библиотека, которая может использоваться как в совокупности с фреймворками, так и без связи с ними. Она умеет создавать формы, осуществлять их проверку и заполнять их определенными данными. Также в ее функционал входит ряд других возможностей. Помимо этого, библиотека позволяет реализовать защиту от CSRF.

Чтобы установить ее, используется Flask-WTF – специальное расширение, которое делает совместимым Flask и WTForms. В функционал также входят такие функции, как загрузка файлов, ввод каптчи, интернационализация, и так далее. 

Чтобы осуществить инсталляцию библиотеки, используется такая инструкция. 

(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, submit. Эти переменные нужны, чтобы осуществить рендеринг полей формы, а также получения данных, которые в них находятся. Помимо этого, через них можно изменять содержимое этих форм. 

При создании этой формы использовались два StringField, TextAreaField, SubmitField

Каждый раз, при создании поля, функции-конструктору, используемой для этого, передаются определенные аргументы:

  1. Строка, содержащая метку, отображаемую внутри тега <label> в момент рендеринга поля. 
  2. Список валидаторов (элементов для проверки полей формы), передача которых осуществляется в виде аргументов-ключевых слов. Под валидаторами подразумеваются функции или классы, определяющие, правильно ли введены данные в поле.
    Для каждого поля возможно применение нескольких валидаторов, которые разделяются запятыми. 

Что касается валидаторов, то их можно создать самостоятельно или воспользоваться уже предустановленными в wtforms.validators. Так, в этой форме мы использовали два из них:

  1. DataRequired. Проверяет, была ли хоть какая-то информация введена в это поле.
  2. Email. Выполняет проверку, является ли содержимое конкретного поля действующим электронным адресом.

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

Это лишь базовая информация о том, какие бывают формы и валидаторы. Ознакомиться с полным перечнем можно в официальной документации WTForms.

Установка SECRET_KEY

Во Flask_WTF имеется встроенная поддержка возможности предотвращения CSFR-атак. Более того, это данный компонент делает по умолчанию. Как это делается? Путем встраивания в элемент <input> внутри формы специального токена.

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

#...

app.debug = True

app.config['SECRET_KEY'] = 'a really really really really long secret key'




manager = Manager(app)

#...

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

Секретный ключ должен соответствовать следующим требованиям:

  1. Относиться к строковому типу данных.
  2. Желательно, чтобы он был длинным.
  3. Подбираться должен таким образом, чтобы его было трудно разгадать. 

Впрочем, секретный ключ используется не только для генерации CSFR-токенов, но и в других расширениях Flask. 

Важное требование к секретному ключу: он должен быть безопасно сохранен. 

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

Теперь давайте используем следующую инструкцию, чтобы открыть оболочку Python

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

Она будет запущена внутри контекста приложения.

Далее импортируется класс ContactForm и создается экземпляр объекта новой формы. Для этого передаются ее данные таким образом. 

>>>

>>> from forms import ContactForm

>>> from werkzeug.datastructures import MultiDict

>>>

>>>

>>> form1 = ContactForm(MultiDict([('name', 'jerry'),('email', 'jerry@mail.com')]))

>>>

Необходимо учесть, что передача данных осуществляется в виде объекта MultiDict, так как функция-конструктор класса wtfroms.Form принимает аргумент соответствующего типа. 

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

Отличие этих типов в том, что ImmutableMultiDict хранит данные такого же типа, только их нельзя изменять.

А валидация формы осуществляется с использованием метода validate(), который возвращает True в случае успешности проверки. 

>>

>>> form1.validate()

False

>>>

В данном случае проверка формы оказалась неудачной, поскольку в ходе создания объекта не была передана никакая информация. Чтобы получить более подробную информацию об ошибке и обработать ее, необходимо использовать атрибут errors объекта формы.

ОфисГуру
Adblock
detector