Основы Flask: создаем сайт на Python с нуля
Начать знакомство с Flask можно с создания простого приложения, которое выводит “Hello World”. Создаем новый файл main.py и вводим следующий код.
from flask import Flask app = Flask(__name__) @app.route('/')
def index(): return 'Hello World' if __name__ == «__main__»: app.run()
Это приложение “Hello World”, созданное с помощью фреймворка Flask. Если код в main.py не понятен, это нормально. В следующих разделах все будет разбираться подробно. Чтобы запустить main.py, нужно ввести следующую команду в виртуальную среду Python.
(env) gvido@vm:~/flask_app$ python main.py
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Запуск файла main.py запускает локальный сервер для разработки на порте 5000. Осталось открыть любимый браузер и зайти на https://127.0.0.1:5000/, чтобы увидеть приложение Hello World в действии.
Остановить сервер можно с помощью комбинации CTRL+C.
Создание приложения Flask
У каждого Flask-приложения должен быть экземпляр класса. Экземпляр — это WSGI-приложение (WSGI – это интерфейс для взаимодействия сервера с фреймворком), которое показывает, что сервер передает все полученные запросы экземпляру для дальнейшей обработки. Объект класса Flask создается следующим образом:
from flask import Flask app = Flask(__name__)
В первой строке класс Flask импортируется из пакета flask.
Во второй строке создается объект Flask. Для этого конструктору Flask назначается аргумент __name__. Конструктор Flask должен иметь один обязательный аргумент. Им служит название пакета. В большинстве случаев значение __name__ подходит. Название пакета приложения используется фреймворком Flask, чтобы находить статические файлы, шаблоны и т. д.
Создание route (путей)
Маршрут (или путь) используется во фреймворке Flask для привязки URL к функции представления. Эта функция отвечает на запрос. Во Flask декоратор route используется, чтобы связать URL адрес с функций. Вот как маршрут создается.
@app.route('/')
def index(): return 'Hello World'
Этот код назначает функцию index() обработчиком корневого URL в приложении. Другими словами, каждый раз, когда приложение будет получать запрос, где путь — /, вызывается функция index(), и на этом запрос завершается.
Как вариант можно использовать метод add_url_rule() вместо декоратора route для маршрутизации. add_url_rule() — это простой метод, а не декоратор. Помимо URL он принимает конечную точку и название функции представления.
Конечная точка относится к уникальному имени маршрута. Обычно, название функции представления — это и есть конечная точка. Flask может генерировать URL из конечной точки, но об этом позже.
Предыдущий код аналогичен следующему:
def index(): return 'Hello World' app.add_url_rule('/', 'index', index)
Декоратор route используется в большинстве случаев, но у add_url_rule() есть свои преимущества.
Функция представления должна вернуть строку. Если пытаться вернуть что-то другое, сервер ответит ошибкой 500 Internal Sever Error.
Можно создать столько столько, сколько нужно приложению. Например, в следующем списке 3 пути.
@app.route('/')
def index(): return 'Home Page' @app.route('/career/')
def career(): return 'Career Page' @app.route('/feedback/')
def feedback(): return 'Feedback Page'
Когда URL в маршруте заканчивается завершающим слешем (/), Flask перенаправляет запрос без слеша на URL со слешем. Так, запрос к /career будет перенаправлен на /career/.
Для одной функции представления может быть использовано несколько URL. Например:
@app.route('/contact/')
@app.route('/feedback/')
def feedback(): return 'Feedback Page'
В этом случае в ответ на запросы /contact/ или /feedback/, будет вызвана функция feedback().
Если перейти по адресу, для которого нет соответствующей функции представления, появится ошибка 404 Not Found.
Эти маршруты статичны. Большая часть современных приложений имеют динамичные URL. Динамичный URL – это адрес, который состоит из одной или нескольких изменяемых частей, влияющих на вывод страницы.
Например, при создании веб-приложения со страницами профилей, у каждого пользователя будет уникальный id. Профиль первого пользователя будет на странице /user/1, второго — на /user/2 и так далее.
Очень неудобный способ добиться такого результата — создавать маршруты для каждого пользователя отдельно.
https://www.youtube.com/watch?v=jgAVGtkk03Q\u0026list=PL0lO_mIqDDFXiIQYjLbncE9Lb6sx8elKA
Вместе этого можно отметить динамические части URL как (переменные). Эти части потом будут передавать ключевые слова функции отображения. Следующий код демонстрирует путь с динамическим элементом.
@app.route('/user//')
def user_profile(id): return «Profile page of user #{}».format(id)
В этом примере на месте будет указываться часть URI, которая идет после /user/. Например, если зайти на /user/100/, ответ будет следующим.
Profile page of user #100
Этот элемент не ограничен числовыми id. Адрес может быть /user/cowboy/, /user/foobar10/, /user/@@##/ и так далее. Но он не будет работать со следующими URI: /user/, /user/12/post/. Можно ограничить маршрут, чтобы он работал только с числовыми id после /user/. Это делается с помощью конвертера.
По умолчанию динамические части URL передаются в функцию в виде строк. Это можно изменить с помощью конвертера, который указывается перед динамическими элементами URL с помощью . Например, /user// будет работать с адресами /user/1/, /user/200/ и другими. Но /user/cowboy/, /user/foobar10/ и /user/@@##/ не подойдут.
В этом списке все конвертеры, доступные во Flask:
string | принимает любые строки (значение по умолчанию). |
int | принимает целые числа. |
float | принимает числа с плавающей точкой. |
path | принимает полный путь включая слеши и завершающий слеш. |
uuid | принимает строки uuid (символьные id). |
Запуск сервера
Для запуска сервера разработки нужно использовать метод run() объекта Flask.
if __name__ == «__main__»: app.run()
Условие __name__ == «__main__» гарантирует, что метод run() будет вызван только в том случае, если main.py будет запущен, как основная программа. Если попытаться использовать метод run() при импорте main.py в другой модуль Python, он не вызовется.
Важно: сервер разработки Flask используется исключительно для тестирования, поэтому его производительность невысокая.
Теперь должно быть понятнее, как работает main.py.
Режим отладки (Debug)
Баги неизбежны в программировании. Поэтому так важно знать, как находить ошибки в программе и исправлять их. Во Flask есть мощный интерактивный отладчик, который по умолчанию отключен. Когда он выключен, а в программе обнаруживается ошибка, функция показывает 500 Internal Sever Error. Чтобы увидеть это поведение наглядно, можно специально добавить баг в файл main.py.
from flask import Flask app = Flask(__name__) @app.route('/')
def index(): print(i) return 'Hello World' if __name__ == «__main__»: app.run()
В этом случае программа пытается вывести значение неопределенной переменной i, что приводит к ошибке. Если открыть https://127.0.0.1:5000/, то появится ошибка 500 Internal Sever Error:
Тем не менее сам браузер не сообщает о типе ошибки. Если посмотреть в консоль, то можно увидеть отчет об ошибке. В данном случае он выглядит вот так:
File «/home/gvido/flask_app/env/lib/python3.5/site-packages/flask/app.py», line 1612, in full_dispatch_request
rv = self.dispatch_request()
File «/home/gvido/flask_app/env/lib/python3.5/site-packages/flask/app.py», line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File «main.py», line 13, in index
print(i)
NameError: name 'i' is not defined
Когда режим отладки выключен, после изменения кода нужно каждый раз вручную запускать сервер, чтобы увидеть изменения. Но режим отладки будет перезапускать его после любых изменений в коде.
Чтобы включить режим, нужно передать аргумент debug=True методу run():
if __name__ == «__main__»: app.run(debug=True)
Еще один способ — указать значение True для атрибута debug.
from flask import Flask app = Flask(__name__)
app.debug = True
После обновления файл main.py следующим образом его можно запускать.
from flask import Flask app = Flask(__name__) @app.route('/')
def index(): print(i) return 'Hello World' if __name__ == «__main__»: app.run(debug=True)
Теперь при открытии https://127.0.0.1:5000/ на странице будет отладчик.
Теперь, когда отладчик включен, вместо ошибки 500 Internal Server на странице будет отображаться отчет об ошибке. Он в полной мере описывает, какая ошибка случилась. Внизу страницы видно, что оператор print пытался вывести значение неопределенной переменной i. Там же указан тип ошибки, NameError, что подтверждает то, что ошибка заключается в том, что имя i не определено.
Кликнув на строчку кода на странице вывода ошибки, можно получить исходный код, где эта ошибка обнаружена, а также предыдущие и следующие строчки. Это помогает сразу понять контекст ошибки.
При наведении на строчку кода отображается иконка терминала. Нажав на нее, откроется консоль, где можно ввести любой код Python.
В ней можно проверить локальные переменные.
Если консоль открывается первый раз, то нужно ввести PIN-код.
Это мера безопасности, призванная ограничить доступ к консоли неавторизованным пользователям. Посмотреть код можно в консоли при запуске сервера. Он будет указан в начале вывода.
Завершить урок стоит созданием еще одного приложения Flask с применением всех имеющихся знаний.
Создаем еще один файл main2.py со следующим кодом:
from flask import Flask app = Flask(__name__) @app.route('/')
def index(): return 'Hello Flask' @app.route('/user//')
def user_profile(user_id): return «Profile page of user #{}».format(user_id) @app.route('/books//')
def books(genre): return «All Books in {} category».format(genre) if __name__ == «__main__»: app.run(debug=True)
Если запустить файл и зайти на https://127.0.0.1:5000/, браузер поприветствует выражением «Hello Flask»:
В этой новой версии приложения есть два динамических пути. Если в браузере ввести https://127.0.0.1:5000/user/123/, откроется страница со следующим содержанием:
Стоит заметить, что путь /user// будет работать только с теми URL, где динамическая часть (user_id) представлена числом.
Чтобы проверить второй динамический путь, нужно открыть https://127.0.0.1:5000/books/sci-fi/. В этот раз получится следующее:
Если сейчас попробовать открыть URL, который не определен в путях, выйдет ошибка 404 Not Found. Например, такой ответ получите при попытке перейти на https://127.0.0.1:5000/products.
Как Flask обрабатывает запрос?
Откуда Flask знает, какую функцию выводить, когда он получает запрос от клиента?
Flask сопоставляет URL и функции отображения, которые будут выводиться. Определение соответствий (маршрутизация) создается с помощью декоратора route или метода add_url_rule() в экземпляре Flask. Получить доступ к этим соответствиям можно с помощью атрибута url_map у экземпляра Flask.
>>>
>>> from main2 import app
>>> app.url_map
Map([ index>, static>, books>, user_profile>])
>>>
Как видно, есть 4 правила. Flask определяет соответствия URL в следующем формате:
url pattern, (comma separated list of HTTP methods handled by the route) -> view function to execute
Путь /static/ автоматически добавляется для статических файлов Flask. О работе со статическими файлами речь пойдет в отдельном уроке «Обслуживание статических файлов во Flask».
Мега-Учебник Flask, Часть 1: «Привет, Мир!»
Это первая статья в серии, где я буду документировать мой опыт написания веб-приложения на Python, используя микрофреймворк Flask. Здесь список всех статей в серии:
Часть 1: Привет, Мир!
Часть 2: Шаблоны Часть 3: Формы Часть 4: База данных Часть 5: Вход пользователей Часть 6: Страница профиля и аватары Часть 7: Unit-тестирование Часть 8: Подписчики, контакты и друзья Часть 9: Пагинация Часть 10: Полнотекстовый поиск Часть 11: Поддержка e-mail Часть 12: Реконструкция Часть 13: Дата и время Часть 14: I18n and L10n Часть 15: Ajax Часть 16: Отладка, тестирование и профилирование Часть 17: Развертывание на Linux (даже на Raspberry Pi!) Часть 18: Развертывание на Heroku Cloud
Моя предыстория
Я разработчик ПО с двузначным числом лет опыта разработки комплексных приложений на нескольких языках. Впервые я познакомился с Python для создания привязок к C++ библиотеке на работе. Вдобавок к Python, я писал веб-приложения на PHP, Ruby, Smalltalk и, верите вы или нет, еще на С++. Из всего этого, я нахожу комбинацию Python/Flask самой гибкой.
Приложение
Приложение, которое я собираюсь разрабатывать как часть этого руководства, является сервером микроблогов, и я решил назвать его microblog. Довольно креативно, я знаю.
Во время нашего прогресса я затрону следующие темы:
- Управление пользователями, включая управление входами, сессиями, ролями пользователя, профилями и пользовательскими аватарами
- Управление базой данных, включая миграцию
- Поддержка форм, включая валидацию полей
- Пагинация длинных списков элементов
- Полнотекстовый поиск
- E-mail уведомления пользователей
- HTML шаблоны
- Поддержка нескольких языков
- Кеширование и другая оптимизация производительности
- Методы отладки для серверов разработки и продакшна
- Установка на продакшн сервер
Как видите, я весьма значительно берусь за все это. Надеюсь, что это приложение, когда я его закончу, станет чем-то вроде шаблона для написания других веб-приложений.
Требования
Если ваш компьютер поддерживает Python 2.6/2.7, то все, вероятно, пойдет хорошо. Приложение из руководства должно нормально работать на Windows, OS X и Linux.
Это руководство подразумевает, что вы знакомы с окном терминала (командной консолью в случае Windows), и вы знаете основные команды для работы с файлами вашей ОС. Если это не так, то перед тем как продолжить, я рекомендую вам ознакомиться с тем, как создавать директории, копировать файлы и т.д.
, используя консоль. Наконец, вы должны чувствовать себя свободно в написании кода на Python. Знакомство с модулями и пакетами этого языка также не помешает.
Установка Flask
Ну что ж, приступим!
Если у вас еще не установлен Python 2.7, то берем его отсюда.
Теперь нам нужно установить Flask и несколько расширений, которые мы будем использовать. Я предпочитаю создание виртуального окружения, где все это будет установлено таким образом, что ваша основная установка Python затронута не будет. В качестве бонуса, вам не нужен будет root доступ для установки таким способом.
Итак, открываем терминал, выбираем место, где будет ваше приложение, и создаем новую папку, в которой оно будет содержаться. Назовем эту папку microblog.
Далее скачиваем virtualenv.py и кладем его внутрь новой папки.
Чтобы создать новое окружение введите следующую команду:python virtualenv.py flask
Эта команда создаст полноценное окружение Python внутри папки flask
Виртуальные окружения могут быть активированы и деактивированы по желанию.
Активированное окружение добавляет путь своей папки bin в path системы, например, когда вы вызываете интерпретатор python, то получаете версию текущего окружения, а не системную.
Лично я никогда не любил это свойство, поэтому ни разу не активировал ни одно из моих окружений, вместо этого я просто вызывал тот интерпретатор, который хотел, печатая его путь.
Прим. пер.: Перед тем как вы начнете вводить команды, хочу отметить, что в х к девятой части отметится баг в flask-whooshalchemy, исправленную версию можнонужно скачать отсюда (репозиторий автора)
Если вы пользователь Linux, OS x или Cygwin, установите flask и расширения, вводя следующие команды одну за одной:Список командflask/bin/pip install flask==0.9
flask/bin/pip install flask-login
flask/bin/pip install flask-openid
flask/bin/pip install flask-mail
flask/bin/pip install sqlalchemy==0.7.9
flask/bin/pip install flask-sqlalchemy==0.16
flask/bin/pip install sqlalchemy-migrate
flask/bin/pip install flask-whooshalchemy==0.54a
flask/bin/pip install flask-wtf==0.8.4
flask/bin/pip install pytz==2013b
flask/bin/pip install flask-babel==0.8
flask/bin/pip install flup
Если же вы пользователь Windows, то команды слегка отличаются:Список командflaskScriptspip install flask==0.9
flaskScriptspip install flask-login
flaskScriptspip install flask-openid
flaskScriptspip install sqlalchemy==0.7.9
flaskScriptspip install flask-sqlalchemy==0.16
flaskScriptspip install sqlalchemy-migrate
flaskScriptspip install flask-whooshalchemy==0.54a
flaskScriptspip install flask-wtf==0.8.4
flaskScriptspip install pytz==2013b
flaskScriptspip install flask-babel==0.8
flaskScriptspip install flup
Эти команды скачают и установят все пакеты, которые мы будем использовать в нашем приложении.
Учтите, что мы собираемся использовать Flask 0.9, а не последнюю версию. Flask 0.10 не было довольно долго и некоторые расширения не готовы для работы с данной версией. Также есть несколько несовместимостей между пакетами и последней версией pip, которые решены использованием конкретных версий для установки.
Windows пользователей ждет еще один шаг. Наблюдательный читаель заметит, что в списке команд для Windows отсутствует flask-mail. Это расширение не устанавливается чисто на Windows, поэтому мы пойдем обходным путем:
flaskScriptspip install —no-deps lamson chardet flask-mail
Я не буду вдаваться в подробности, поэтому если вы хотите узнать больше, прочтите документацию к flask-mail.
Если установка всех пакетов прошла успешно, вы можете удалить virtualenv.py, поскольку файл нам больше не понадобится.
«Hello, World!» в Flask
Теперь у вас есть подпапка flask, в вашей папке microblog, содержащая интерпретатор Python и фреймворк Flask с расширениями, которые мы будем использовать в этом приложении. Настало время написать наше первое веб-приложение!
После того как вы переместились папку microblog, давайте создадим основную структуру папок для нашего приложения:
mkdir app
mkdir app/static
mkdir app/templates
mkdir tmp
В папку app мы поместим само наше приложение. Подпапка static нужна для хранения статики, такой как картинки, javascript файлы и таблицы стилей. Подпапка templates, очевидно, предназначена для хранения наших шаблонов.
Давайте начнем с создания простого скрипта инициализации нашего пакета app (файл app/__init__.py)
from flask import Flask
app = Flask(__name__)
from app import views
Скрипт выше просто создает объект приложения (наследуя Flask), затем импортирует модуль представлений, который мы еще не написали.
Представления — это обработчики, которые отвечают на запросы веб-браузера. Представления в Flask пишутся как Python функции. Каждая функция представления сопоставляется с одним или несколькими запросами URL.
Напишем нашу первую функцию представления (файл app/views.py)
from app import app
@app.route('/')
@app.route('/index')
def index():
return «Hello, World!»
Это весьма простое представление, которое просто возвращает строку для отображения в пользовательском браузере. Два декоратора route создают привязку адресов / и /index к этой функции.
Последним шагом для получения полностью работающего веб-приложения будет создание скрипта, который стартует веб-сервер нашего приложения. Давайте назовем скрипт run.py и положим его в корневой каталог (microblog/):
#!flask/bin/python
from app import app
app.run(debug = True)
Скрипт просто импортирует переменную app из нашего пакета app и вызывает метод run для того, чтобы запустить сервер. Помните, что переменная app — экземпляр класса Flask, мы создали его выше.
Для запуска вашего приложения просто запустите скрипт. На OS X, Linux и Cygwin вам следует пометить файл исполняемым перед тем как вы сможете его запустить. chmod a+x run.py
Тогда скрипт может быть вызван просто: ./run.py
В Windows процесс немного отличается. Нет необходимости помечать файл исполняемым. Вместо этого вам нужно запустить скрипт как аргумент интерпретатора Python: flask/Scripts/python run.py
После старта сервер будет прослушивать порт 5000, ожидая соединений. Теперь откроем браузер и введем следующий URL в адресную строку: Или же вы можете использовать эту ссылку: http://localhost:5000/index
Теперь вы увидели маршрутизацию в действии? Первый URL привязан к /, в то время как второй к /index. Оба маршрута ассоциированы с нашей функцией представления, поэтому они дают одинаковый результат. Если вы введете любой другой маршрут, то получите ошибку, так как только эти два были привязаны к функции представления.
Когда вы закончите играть с сервером вы можете просто нажать Ctrl-C, чтобы остановить его. И этим я хочу закончить первую часть этого руководства. Те из вас, кто поленился печатать, могут скачать код из этого руководства ниже:
Скачать microblog-0.1.zip.
Обратите внимание, что вам нужно установить Flask, чтобы запустить приложение из архива выше.
Что дальше
В следующей части серии мы изменим наше маленькое приложение для использования HTML шаблонов. Надеюсь увидимся в следующей части.
Мигель
Создание веб-приложения с использованием Python Flask
В предыдущей статье в блоге Timeweb Cloud мы познакомились с веб-разработкой на python с использованием Flask и рассмотрели способы работы с входящими данными. В этом туториале мы шагнем чуть дальше и напишем простое веб-приложение на python с базой данных для авторизации пользователей.
Мы будем работать в PyCharm+pipenv, а сайт сделаем на HTML+CSS. Операционная система — Win 10. Установка Flask, PyCharm и pipenv подробно описана в этой статье.
В рамках статьи мы будем использовать тестовые, учебные примеры, которые не подойдут для реализации на продакшене. Например, для проверки пароля в БД необходимо хранить хэш пароля и сравнивать хэши, а не пароли. Также для работы с СУБД нужно использовать ORM, а не писать «сырой» SQL (подробнее про ORM см. здесь).
Кстати, в официальном канале Timeweb Cloud собрали комьюнити из специалистов, которые говорят про IT-тренды, делятся полезными инструкциями и даже приглашают к себе работать.
Для начала работы создадим директорию проекта — Timeweb. В ней разместим директории templates и static, а в директории static создадим директорию css. Теперь структура проекта выглядит так:
Timeweb|— templates|— static
| — css
БД для логинов и паролей
После того, как вы установите Flask и остальные инструменты, можно перейти к работе. Для хранения данных пользователей будем использовать СУБД SQlite. Она отлично подходит для небольших проектов.
Её основное преимущество заключается в автономности: для работы с ней не потребуется сервер. К тому же в python встроен модуль sqlite3 для работы с ней.
Но если вы решите работать с СУБД на сервере, то обратите внимание на облачные серверы Timeweb Cloud.
В директории проекта создаем файл db.py. В файле импортируем модуль sqlite3 и создаем базу данных и таблицу с логинами и паролями:
import sqlite3
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 во избежание проблем с БД.
Для создания базы данных выполняем команду:
python db.py
Авторизация
Основная форма
Сначала создадим форму, с помощью которой будет осуществляться авторизация в абстрактный сервис.
В директории templates создаем файл authorization.html с содержанием:
Логин Пароль Войти Регистрация
Здесь важно 3 момента:
- — указываем, что будем использовать POST-запросы;
- label for=»Login» и label for=»Password» — отмечаем Login, который в дальнейшем будем обрабатывать с помощью метода get() из модуля request;
- — сообщаем HTML, где хранится css-файл.
В директории /static/css создаем файл auth.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; /*Размер внутренних отступов контейнера*/
}
В итоге наша форма будет выглядеть так:
Сообщение для успешной авторизации
Если пользователь ввёл верную пару логин-пароль, то выведем соответствующее сообщение.
В директории templates создаем файл successfulauth.html с содержанием:
Вы успешно авторизовались
В директории /static/css создаем файл successfulauth.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; /*Центровка текста*/}.container { padding: 30px; /*Размер внутренних отступов контейнера*/
}
Сообщение при неудачной авторизации
В директории templates создаем файл auth_bad.html с содержанием:
Введен неправильный логин или пароль
В директории /static/css создаем файл auth_bad.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; /*Центровка текста*/}.container { padding: 30px;/*Размер внутренних отступов контейнера*/
}
Теперь создадим форму для регистрации.
Регистрация
С помощью формы регистрации пользователь сможет создать свой аккаунт.
В templates создаем файл registration.html:
Логин Пароль Зарегистрироваться
В /static/css создаем regis.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; /*Размер внутренних отступов контейнера*/
}
- Форма регистрации будет выглядть так:
- При завершении регистрации пользователь увидит такое сообщение:
- Для этого в templates создаем файл successfulregis.html:
Вы успешно зарегистрировались Вернуться к авторизации
А в /static/css создаем successfulregis.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; /*Центровка текста*/}.container { padding: 20px;/*Размер внутренних отступов контейнера*/
}
Декоратор авторизации
После создания всех форм и БД мы можем начатьразработку веб-приложения Flask. Для отправления html-документа в ответ на запрос клиента в Flask нужно использовать метод render_template(). Эта функция модуля Flask используется для отображения шаблонов из папки templates.
Сейчас каталог проекта имеет такую структуру:
Timeweb|— db.py|— login_password.db|— templates| `— authorization.html| `— auth_bad.html| `— successfulauth.html| `— successfulregis.html| `— registration.html|— static| — css| `— auth_bad.css| `— auth.css| `— successfulauth.css| `— regis.css
| `— successfulregis.css
В директории проекта /Timeweb создаем файл main.py, в котором импортируем необходимые модули из Flask и добавляем код для авторизации пользователей. Подробнее об аутентификации рекомендуем почитать здесь.
from flask import Flask, request, render_templateimport sqlite3@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 пользователь попадает из формы авторизации. Вот код декоратора, добавляем его в конец main.py:
@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_templateimport sqlite3app = 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()