Create web apps with python flask

Создание веб-приложения с использованием Python Flask

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

Мы будем работать в PyCharm+pipenv, а сайт сделаем на HTML+CSS. Операционная система — Win 10. Установка Flask, PyCharm и pipenv подробно описана в этой статье.

В рамках статьи мы будем использовать тестовые, учебные примеры, которые не подойдут для реализации на продакшене. Например, для проверки пароля в БД необходимо хранить хэш пароля и сравнивать хэши, а не пароли. Также для работы с СУБД нужно использовать ORM, а не писать «сырой» SQL (подробнее про ORM см. здесь).

Кстати, в официальном канале Timeweb Cloud собрали комьюнити из специалистов, которые говорят про IT-тренды, делятся полезными инструкциями и даже приглашают к себе работать.

БД для логинов и паролей

После того, как вы установите Flask и остальные инструменты, можно перейти к работе. Для хранения данных пользователей будем использовать СУБД SQlite. Она отлично подходит для небольших проектов. Её основное преимущество заключается в автономности: для работы с ней не потребуется сервер. К тому же в python встроен модуль sqlite3 для работы с ней. Но если вы решите работать с СУБД на сервере, то обратите внимание на облачные серверы Timeweb Cloud.

Читайте также:  Файл стилей темы style css

Итак, работа с модулем начинается с импорта:

Теперь мы можем создать БД и таблицу с логинами и паролями:

db_lp = sqlite3.connect('login_password.db')
cursor_db = db_lp.cursor()
sql_create = '''CREATE TABLE passwords(
login TEXT PRIMARY KEY,
password TEXT NOT NULL);'''

cursor_db.execute(sql_create)
db_lp.commit()

cursor_db.close()
db_lp.close()

Распишем подробно, что этот код делает:

  • Подключаемся к БД с помощью метода connect(). Метод будет искать файл login_password.db в каталоге проекта. Если не найдет, то создаст самостоятельно.
  • Создаем объект cursor_db для взаимодействия с БД;
  • sql_create — это SQL-запрос для создания таблицы с логинами и паролями;
  • С помощью метода execute() выполняем sql_create;
  • Сохраняем изменения в БД методом commit();
  • Закрываем объекты cursor_db и db_lp во избежание проблем с БД;

Авторизация

Основная форма

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

  • — указываем, что будем использовать POST-запросы;
  • label for=»Login» и label for=»Password» — отмечаем Login, который в дальнейшем будем обрабатывать с помощью метода get() из модуля request;
  • >»> — сообщаем HTML, где хранятся css файл. Чуть дальше подробнее разберем, где нужно его размещать.
form font: 14px Stem-Regular,arial, sans-serif;/*Выбираем шрифт */ 
border: 1px solid black;/*Цвет, размер и тип границы */
-webkit-border-radius: 20px;/*Скругляем углы */
color: #777991;/*Цвет label */
width: 25%; /*Ширина формы */
margin-right: auto; /*Положение формы */
margin-left: auto; /*Положение формы */
text-align: center; /*Центровка текста*/

>

input[type=text], input[type=password] text-align: center; /*Центровка текста*/
-webkit-border-radius: 4px;/*Скругляем углы */
width: auto; /*Ширина */
padding: 15px 20px; /*Размер внутренних отступов*/
margin: 10px 0; /*Размер внешних отступов*/
margin-right: auto; /*Размер внешних отступов справа*/
margin-left: auto; /*Размер внешних отступов слева*/
display: block; /*тип отображения*/
border: 1px solid #050c26;/*Цвет, размер и тип границы */
box-sizing: border-box; /*Размер объекта по отношению к родительскому */
font: 14px Stem-Regular,arial, sans-serif;/*Выбираем шрифт */
color: #777991;/*Цвет текста в input */
>

button font: 16px Stem-medium, arial, sans-serif; /*Выбираем шрифт кнопки */
background-color: #454cee; /*Выбираем цвет фона */
-webkit-border-radius: 8px; /*Закругление */
color: white; /*Выбираем цвет текста*/
padding: 16px 20px; /*Размер внутренних отступов*/
margin: 8px 0;/*Размер внешних отступов*/
border: none; /*Без границы*/
cursor: pointer; /*Изменение курсора при наведении на кнопку*/
width: auto; /*Ширина*/
>

button:hover <
opacity: 0.9; /*Изменение яркости кнопки при наведении*/
>

.container padding: 20px; /*Размер внутренних отступов контейнера*/
>

Вот как выглядит эта форма:

Сообщение для успешной авторизации

Если пользователь ввёл верную пару логин-пароль, то выведем соответствующее сообщение.






>">
form font: 14px Stem-Regular,arial, sans-serif;/*Выбираем шрифт */ 
border: 1px solid black;/*Цвет, размер и тип границы */
-webkit-border-radius: 20px;/*Скругляем углы */
color: #777991;/*Цвет label */
width: 25%; /*Ширина формы */
margin-right: auto; /*Положение формы */
margin-left: auto; /*Положение формы */
text-align: center; /*Центровка текста*/
>
.container padding: 30px; /*Размер внутренних отступов контейнера*/
>

Сообщение при неудачной авторизации







>">
form font: 14px Stem-Regular,arial, sans-serif;/*Выбираем шрифт */ 
border: 1px solid black;/*Цвет, размер и тип границы */
-webkit-border-radius: 20px;/*Скругляем углы */
color: #777991;/*Цвет label */
width: 25%; /*Ширина формы */
margin-right: auto; /*Положение формы */
margin-left: auto; /*Положение формы */
text-align: center; /*Центровка текста*/

>

.container padding: 30px;/*Размер внутренних отступов контейнера*/
>

Теперь создадим форму для регистрации.

Регистрация

С помощью формы регистрации пользователь сможет создать свой аккаунт. Вот HTML и CSS основной формы:













>">
form font: 14px Stem-Regular,arial, sans-serif;/*Выбираем шрифт */ 
border: 1px solid black;/*Цвет, размер и тип границы */
-webkit-border-radius: 20px;/*Скругляем углы */
color: #777991;/*Цвет label */
width: 25%; /*Ширина формы */
margin-right: auto; /*Положение формы */
margin-left: auto; /*Положение формы */
text-align: center; /*Центровка текста*/

>

input[type=text], input[type=password] text-align: center; /*Центровка текста*/
-webkit-border-radius: 4px;/*Скругляем углы */
width: auto; /*Ширина */
padding: 15px 20px; /*Размер внутренних отступов*/
margin: 10px 0; /*Размер внешних отступов*/
margin-right: auto; /*Размер внешних отступов справа*/
margin-left: auto; /*Размер внешних отступов слева*/
display: block; /*тип отображения*/
border: 1px solid #050c26;/*Цвет, размер и тип границы */
box-sizing: border-box; /*Размер объекта по отношению к родительскому */
font: 14px Stem-Regular,arial, sans-serif;/*Выбираем шрифт */
color: #777991;/*Цвет текста в input */
>

button font: 16px Stem-medium, arial, sans-serif; /*Выбираем шрифт кнопки */
background-color: #454cee; /*Выбираем цвет фона */
-webkit-border-radius: 8px; /*Закругление */
color: white; /*Выбираем цвет текста*/
padding: 16px 20px; /*Размер внутренних отступов*/
margin: 8px 0;/*Размер внешних отступов*/
border: none; /*Без границы*/
cursor: pointer; /*Изменение курсора при наведении на кнопку*/
width: auto; /*Ширина*/
>

button:hover <
opacity: 0.9; /*Изменение яркости кнопки при наведении*/
>

.container padding: 20px; /*Размер внутренних отступов контейнера*/
>

Форма регистрации выглядит вот так:

При завершении регистрации пользователь увидит такое сообщение:

form font: 14px Stem-Regular,arial, sans-serif;/*Выбираем шрифт */ 
border: 1px solid black;/*Цвет, размер и тип границы */
-webkit-border-radius: 20px;/*Скругляем углы */
color: #777991;/*Цвет label */
width: 25%; /*Ширина формы */
margin-right: auto; /*Положение формы */
margin-left: auto; /*Положение формы */
text-align: center; /*Центровка текста*/

>

.container padding: 20px;/*Размер внутренних отступов контейнера*/
>

Декоратор авторизации

После создания всех форм и БД мы можем начать разработку веб-приложения Flask. Для отправления html-документа в ответ на запрос клиента в Flask нужно использовать метод render_template()

Этот метод Flask использует папку templates для хранения html-файлов в каталоге проекта. Нам необходимо создать её. Также в html-документах нужно указать относительную ссылку на css. В нашем случае мы размещаем их в соседней папке static/css в каталоге проекта, чтобы не допускать беспорядка в файлах. Сейчас каталог проекта с html и css имеет такую структуру:

Timeweb
|— template
| `— authorization.html
| `— auth_bad.html
| `— successauth.html
| `— successregis.html
| `— registration.html
|— static
| — css
| `— auth_bad.css
| `— auth.css
| `— successauth.css
| `— regis.css
| `— successfulregis.css

Импортируйте пакет Flask и другие модули:

from flask import Flask, request, render_template

Код для авторизации пользователей представлен ниже. Подробнее об аутентификации рекомендуем почитать здесь.

@app.route('/authorization', methods=['GET', 'POST'])
def form_authorization():
if request.method == 'POST':
Login = request.form.get('Login')
Password = request.form.get('Password')

db_lp = sqlite3.connect('login_password.db')
cursor_db = db_lp.cursor()
cursor_db.execute(('''SELECT password FROM passwords
WHERE login = '<>';
''').format(Login))
pas = cursor_db.fetchall()

cursor_db.close()
try:
if pas[0][0] != Password:
return render_template('auth_bad.html')
except:
return render_template('auth_bad.html')

db_lp.close()
return render_template('successfulauth.html')

return render_template('authorization.html')
  • Пользователь переходит на /authorization — это GET-запрос и декоратор возвращает authorization.html;
  • Когда пользователь введет логин, пароль и нажмет кнопку “Войти”, сервер получит POST-запрос, который декоратор будет обрабатывать. Декоратор получит логин и пароль, которые ввел пользователь;
  • Затем подключаемся к БД и выполняем SQL-запрос к ней. С помощью cursor_db.execute() и cursor_db.fetchall() получаем строку password(возможно, пустую), соответствующую введенному логину;
  • Из строки “вытаскиваем” пароль и:
    • Если строка пустая, то это вызовет ошибку (выход за пределы массива), которую мы обрабатываем конструкцией try-except и сообщаем пользователю о неверных введенных данных. Декоратор завершает работу;
    • Если пароль в БД не совпадает с полученным паролем, то просто возвращает сообщение о некорректности данных и завершаем работу;
    • Если пароль верный, то выдаем сообщение о успешной авторизации и завершаем работу Flask- декоратора.

    Декоратор регистрации

    На страницу /registration пользователь попадает из формы авторизации. Вот код декоратора:

    @app.route('/registration', methods=['GET', 'POST'])
    def form_registration():

    if request.method == 'POST':
    Login = request.form.get('Login')
    Password = request.form.get('Password')

    db_lp = sqlite3.connect('login_password.db')
    cursor_db = db_lp.cursor()
    sql_insert = '''INSERT INTO passwords VALUES('<>','<>');'''.format(Login, Password)

    cursor_db.execute(sql_insert)
    db_lp.commit()

    cursor_db.close()
    db_lp.close()

    return render_template('successfulregis.html')

    return render_template('registration.html')
    • Сначала обрабатывается GET-запрос /registration. Возвращаем registration.html;
    • Когда пользователь введет данные и нажмет кнопку “Зарегистрироваться”, сервер получит POST-запрос. Из него получаем Login и Password;
    • Подключаемся к БД;
    • sql_insert — запрос на добавление новой строки с данными пользователя;
    • Выполняем sql_insert и сохраняем изменения;
    • Закрываем cursor_db, db_lp и возвращаем сообщение об успешной регистрации.

    Полный код программы

    from flask import Flask, request, render_template
    import sqlite3

    app = Flask(__name__)

    @app.route('/authorization', methods=['GET', 'POST'])
    def form_authorization():
    if request.method == 'POST':
    Login = request.form.get('Login')
    Password = request.form.get('Password')

    db_lp = sqlite3.connect(login_password.db')
    cursor_db = db_lp.cursor()
    cursor_db.execute(('''SELECT password FROM passwords
    WHERE login = '<>';
    ''').format(Login))
    pas = cursor_db.fetchall()

    cursor_db.close()
    try:
    if pas[0][0] != Password:
    return render_template('auth_bad.html')
    except:
    return render_template('auth_bad.html')

    db_lp.close()
    return render_template('successfulauth.html')

    return render_template('authorization.html')

    @app.route('/registration', methods=['GET', 'POST'])
    def form_registration():

    if request.method == 'POST':
    Login = request.form.get('Login')
    Password = request.form.get('Password')

    db_lp = sqlite3.connect('login_password.db')
    cursor_db = db_lp.cursor()
    sql_insert = '''INSERT INTO passwords VALUES('<>','<>');'''.format(Login, Password)


    cursor_db.execute(sql_insert)

    cursor_db.close()

    db_lp.commit()
    db_lp.close()

    return render_template('successfulregis.html')

    return render_template('registration.html')


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

    Источник

Оцените статью