Этой статьёй я начинаю перевод обновленного учебника по Flask от Мигеля Гринберга. Перевод издания 2018 остаётся достаточно актуальным для изучения веб-фреймворка, но обновление коснулось многих используемых пакетов, что привело к изменению каждой главы.
В этот раз автор выпустил весь учебник сразу, а не постепенно как издание 2018, постараюсь со стабильной периодичностью выпускать продолжение. Перед выпуском новой статьи весь материал будет обязательно проверен на практике.
Репозиторий издания 2018 переехал, теперь он доступен здесь.
Оглавление
Глава 1: Привет, мир! (Эта статья)
Введение
Что такое мега-учебник Flask?
Еще в 2012 году Мигель решил завести свой блог по разработке программного обеспечения. Поскольку в глубине души он сторонник «сделай сам», вместо использования Blogger или WordPress Мигель сел и написал свой собственный движок для блогов, используя тогда еще малоизвестный веб‑фреймворк под названием Flask. Он знал, что хочет написать код на Python, и сначала попробовал Django, который в то время был самым популярным веб‑фреймворком на Python. Но, к сожалению, Django показался ему слишком большим и структурированным для своих нужд. Мигель обнаружил, что Flask дал ему столько же энергии, оставаясь при этом маленьким, непредвзятым и ненавязчивым.
Написание собственного движка для блогов было потрясающим опытом, который дал ему много идей по темам, о которых Мигель хотел вести блог. Вместо того, чтобы писать отдельные статьи по всем этим темам, он решил написать длинный всеобъемлющий учебник, который новички в Python могут использовать для изучения веб‑разработки. И вот так родился мега‑учебник Flask!
Учебник претерпел ряд изменений:
2021: Незначительный пересмотр написанного контента с 2018 года, приуроченный к выпуску Flask 2.0.
С первого дня Мигель взял на себя обязательство предлагать этот учебник бесплатно в своем блоге, и это остается в силе с этим обновлением. Если вы хотите поддержать работу Мигеля, то подробнее об этом можно узнать в его блоге.
Каковы изменения в издании 2024 года?
Если вы знакомы с содержанием 2018/2021 годов, в этом разделе вы узнаете об изменениях и улучшениях, которые Мигель внес для издания 2024 года.
Flask 3.0
Весь проект был обновлен для использования версии Flask 3.0.0, которая является последней на момент написания этих строк. Мигель также убедился, что проект на 100% совместим с версиями 2.3.x, которыми многие люди все еще пользуются.
Наряду с поддержкой Flask 3 он обновил все расширения и зависимости до последних доступных версий.
SQLAlchemy 2.0
Переход на SQLAlchemy 2 был самым большим изменением из всех, поскольку SQLAlchemy внедрили ряд улучшений в свои последние версии 2.x, которыми Мигель хотел воспользоваться. В частности, из обновленного учебника вы узнаете, как:
Определение моделей баз данных с использованием современного синтаксиса, основанного на подсказках по типам, который хорошо сочетается с анализаторами кода и IDE
Использование новых, более мощных интерфейсов запросов, основанных на функции
select()
Замена устаревших «динамических» отношений на рекомендуемые «только для записи».
Bootstrap 5.3
Использование Bootstrap 3 было одной из частей руководства, которой Мигель меньше всего гордился, но из‑за отсутствия хорошей поддержки новых выпусков Bootstrap в экосистеме Flask он надолго отложил обновление.
Теперь Мигель перешел на версию 5.3.2, последнюю на момент написания этих строк. В этом обновлении он показывает вам, как включить Bootstrap в приложение, используя поддержку функций Jinja, таких как макросы, без использования какого‑либо стороннего пакета Python.
Поддержка Python с 3.8 по 3.12
Мигель также хотел убедиться, что у вас будет хороший опыт работы независимо от используемой вами версии Python. Его решением было поддерживать все версии между 3.8 и 3.12.
Для поддержки этого широкого диапазона версий потребовалось внести в учебник два изменения по сравнению с предыдущим изданием:
Чтобы протестировать доставку электронной почты, Мигель показал вам, как использовать класс
DebuggingServer
модуляsmtpd
. К сожалению,smtpd
модуль давно устарел (до Python 3.8) и фактически был удален в Python 3.12. Сейчас он использует для этогоaiosmtpd
пакет сторонних производителей.Мигелю больше всего понравилась функция
datetime.utcnow()
для получения текущего времени в единицах UTC. Эта функция устарела в Python 3.12 и выдает раздражающее его предупреждение при ее использовании в этой версии Python (у него было что сказать по поводу этого устаревания, если вам интересно). В выпуске 2024 года Мигель использует осведомленные временные метки с явным часовым поясом UTC, следуя рекомендации разработчиков Python.
Помимо устаревших рекомендаций, в учебнике все еще сохранились некоторые пережитки старых времен, когда Мигель поддерживал Python 2. Например, классы по‑прежнему создавались с родительским классом object
и метод super()
включал аргументы. Все эти устаревшие шаблоны теперь удалены.
Больше никаких jQuery
Долгое время jQuery был обязательной библиотекой для любой веб‑страницы. Пытаться делать что‑либо во внешнем интерфейсе без jQuery было болезненно, поскольку у каждого браузера были свои особенности и поведение, которые необходимо было учитывать.
Но согласованность API‑интерфейсов браузера за последние годы значительно улучшилась, настолько, что jQuery теперь считается ненужным. Например, Bootstrap до версии 4 включительно содержит все необходимые jQuery в качестве зависимостей, но Bootstrap 5 покончил с этим, и по этой причине Мигель также устранил все виды использования jQuery в этом руководстве, заменив их собственными API браузера.
Что не изменилось в этом обновлении?
Основной аспект руководства, который не изменился, — это расположение глав. В нем по‑прежнему 23 главы, и они такие же, как в редакциях 2018 и 2021 годов.
Мигель думал о замене раздела Heroku, для которого теперь требуется платная учетная запись, но передумал просто потому, что он знает многих людей, которые даже сегодня являются счастливыми клиентами Heroku и познакомились с платформой благодаря этому руководству.
Автор следит за отзывами
Для Мигеля действительно удивительно, что мега‑учебнику Flask почти 12 лет, и что даже спустя все эти годы он продолжает получать комментарии, вопросы и обратную связь от людей, обучающихся с его помощью. Мигель ценит всю поддержку, которую он получал на протяжении многих лет. Это дает ему мотивацию продолжать вносить в него обновления, так что все желающие могут его поддержать своим отзывом в блоге.
Мега-Учебник Flask Глава 1: Привет, мир!
Добро пожаловать! Вы собираетесь отправиться в путешествие, чтобы научиться создавать веб‑приложения с помощью Python и фреймворка Flask. В этой первой главе вы узнаете, как настроить проект Flask. К концу этой главы на вашем компьютере будет запущено простое веб‑приложение Flask!
Все примеры кода, представленные в этом учебнике, размещены в репозитории GitHub. Загрузка кода с GitHub может сэкономить вам много времени при наборе текста, но я настоятельно рекомендую вам вводить код самостоятельно, по крайней мере, для первых нескольких глав. Как только вы лучше познакомитесь с Flask и примером приложения, вы сможете получить доступ к коду непосредственно с GitHub, если ввод текста станет слишком утомительным.
В начале каждой главы я собираюсь дать вам три ссылки на GitHub, которые могут быть полезны при работе с главой. Ссылка Browse откроет репозиторий GitHub для Microblog в том месте, где были добавлены изменения для главы, которую вы читаете, без учета каких‑либо изменений, внесенных в будущие главы. Ссылка Zip — это ссылка для скачивания zip‑файла, содержащего все приложение вплоть до изменений в главе. По ссылке Diff откроется графическое представление всех изменений, внесенных в главу, которую вы собираетесь прочитать.
Ссылки на GitHub для этой главы: Browse, Zip, Diff.
Установка Python
Если у вас на компьютере не установлен Python, установите его прямо сейчас. Если ваша операционная система не предоставляет вам пакет Python, вы можете загрузить установщик с официального веб‑сайта Python. Если вы используете Microsoft Windows вместе с WSL или Cygwin, обратите внимание, что вы будете использовать не версию Python для Windows, а версию для UNIX, которую вам нужно получить из Ubuntu (если вы используете WSL) или Cygwin.
Чтобы убедиться, что ваша установка Python работает, вы можете открыть окно терминала и ввести python3
, или, если это не работает, просто python
. Вот что вы должны ожидать увидеть:
$ python3
Python 3.12.0 (main, Oct 5 2023, 10:46:39) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> _
Интерпретатор Python теперь ожидает интерактивного приглашения, в котором вы можете вводить инструкции Python. В следующих главах вы узнаете, для каких целей полезно это интерактивное приглашение. Но на данный момент вы подтвердили, что Python установлен в вашей системе. Чтобы выйти из интерактивного приглашения, вы можете ввести exit()
и нажать Enter. В версиях Python для Linux и Mac OS X вы также можете выйти из интерпретатора, нажав Ctrl-D. В Windows для выхода используется сочетание клавиш Ctrl-Z, за которым следует Enter.
Установка Flask
Следующим шагом будет установка Flask, но прежде чем я перейду к этому, я хочу рассказать вам о лучших практиках, связанных с установкой пакетов Python.
В Python пакеты, такие как Flask, доступны в общедоступном репозитории, откуда любой может загрузить и установить их. Официальный репозиторий пакетов Python называется PyPI, что расшифровывается как Python Package Index (некоторые люди также называют этот репозиторий «сырной лавкой»). Установить пакет из PyPI очень просто, потому что Python поставляется с инструментом под названием pip
, который выполняет эту работу.
Чтобы установить пакет на свой компьютер, вы используете pip
следующим образом:
$ pip install <package-name>
Интересно, что этот метод установки пакетов в большинстве случаев работать не будет. Если ваш интерпретатор Python был установлен глобально для всех пользователей вашего компьютера, скорее всего, ваша учетная запись обычного пользователя не будет иметь разрешения на внесение в него изменений, поэтому единственный способ заставить команду, приведенную выше, работать — запустить ее из учетной записи администратора. Но даже без этих сложностей подумайте, что происходит, когда вы устанавливаете пакет таким образом. Инструмент pip
загрузит пакет из PyPI, а затем добавит его в вашу установку Python. С этого момента каждый скрипт Python, который есть в вашей системе, будет иметь доступ к этому пакету. Представьте ситуацию, когда вы завершили создание веб‑приложения, используя версию Flask 2, которая была самой последней версией Flask на момент запуска, но теперь ее заменила версия 3. Теперь вы хотите запустить второе приложение, для которого вы хотели бы использовать версию 3, но если вы обновите установленную версию, вы рискуете сломать старое приложение. Вы видите проблему? Было бы идеально, если бы можно было установить Flask версии 2 и сделать его доступным для вашего старого приложения, а также установить Flask версии 3 для вашего нового.
Для решения проблемы поддержки разных версий пакетов для разных приложений в Python используется концепция виртуальных сред. Виртуальная среда — это полная копия интерпретатора Python. При установке пакетов в виртуальной среде общесистемный интерпретатор Python не затрагивается, затрагивается только копия. Итак, решение для получения полной свободы установки любых версий ваших пакетов для каждого приложения заключается в использовании отдельной виртуальной среды для каждого приложения. Дополнительным преимуществом виртуальных сред является то, что они принадлежат пользователю, который их создает, поэтому для них не требуется учетная запись администратора.
Давайте начнем с создания каталога, в котором будет жить проект. Я собираюсь назвать этот каталог микроблог, поскольку это название приложения:
$ mkdir microblog
$ cd microblog
Поддержка виртуальных сред включена во все последние версии Python, поэтому все, что вам нужно сделать для ее создания, это:
$ python3 -m venv venv
С помощью этой команды я прошу Python запустить пакет venv
, который создает виртуальную среду с именем venv
. Первый venv
в команде является аргументом для параметра -m
, который является именем пакета виртуальной среды Python, а второй - именем виртуальной среды, которое я собираюсь использовать для этой конкретной среды. Если вас это смущает, вы можете заменить второе venv
другим именем, которое вы хотите присвоить своей виртуальной среде. В общем, я создаю свои виртуальные среды с именем venv
в каталоге проекта, поэтому всякий раз, когда я с помощью команды cd
захожу в проект, я нахожу соответствующую виртуальную среду.
Обратите внимание, что в некоторых операционных системах вам может потребоваться использовать python
вместо python3
как в приведенной выше команде. Некоторые установки используют python
для выпусков Python 2.x и python3
для выпусков 3.x, в то время как другие сопоставляются python
с выпусками 3.x и вообще не содержат python3
команды.
После завершения выполнения команды у вас будет каталог с именем venv, в котором хранятся файлы виртуальной среды.
Теперь вам нужно сообщить системе, что вы хотите использовать эту виртуальную среду, и вы делаете это, активируя ее. Чтобы активировать вашу совершенно новую виртуальную среду, вы используете следующую команду:
$ source venv/bin/activate
(venv) $ _
Если вы используете окно командной строки Microsoft Windows, команда активации немного отличается:
$ venv\Scripts\activate
(venv) $ _
Если вы работаете в Windows, но используете PowerShell вместо командной строки, то вам следует использовать еще одну команду активации:
$ venv\Scripts\Activate.ps1
(venv) $ _
Когда вы активируете виртуальную среду, конфигурация вашего терминального сеанса изменяется таким образом, что при вводе текста вызывается интерпретатор Python, хранящийся внутри сеансовой переменной python
. Кроме того, в приглашении терминала изменено имя активированной виртуальной среды. Все изменения, внесенные в ваш сеанс терминала, являются временными и конфиденциальными для этого сеанса, поэтому они не сохранятся при закрытии окна терминала. Если вы работаете с несколькими открытыми окнами терминала одновременно, то это совершенно нормально активировать разные виртуальные среды в каждом из них.
Теперь, когда у вас создана и активирована виртуальная среда, вы, наконец, можете установить в нее Flask:
(venv) $ pip install flask
Если вы хотите подтвердить, что в вашей виртуальной среде теперь установлен Flask, вы можете запустить интерпретатор Python и импортировать Flask в него:
>>> import flask
>>> _
Если это утверждение не выдает вам никаких ошибок, можете поздравить себя, поскольку Flask установлен и готов к использованию.
Примечание от переводчика
Посмотреть установленные в виртуальной среде пакеты и их версии можно следующим способом:
pip list
В выводе для последней версии Flask вы получите примерно следующее:
Package Version
------------ -------
blinker 1.7.0
click 8.1.7
colorama 0.4.6
Flask 3.0.2
itsdangerous 2.1.2
Jinja2 3.1.3
MarkupSafe 2.1.5
pip 24.0
Werkzeug 3.0.1
Обратите внимание, что в приведенных выше командах установки не указано, какую версию Flask вы хотите установить. По умолчанию, когда версия не указана, устанавливается последняя версия, доступная в репозитории пакетов. Этот туториал разработан для версии 3 Flask, но также должен работать с версией 2. Приведенная выше команда установит последнюю версию 3.x, которая должна подходить большинству пользователей. Если по какой-либо причине вы предпочитаете следовать этому туториалу для версии Flask для 2.x, вы можете использовать следующую команду для установки последней версии для 1.x:
(venv) $ pip install "flask<3" "werkzeug<3"
Приложение Flask "Привет, мир"
Если вы перейдете на страницу быстрого запуска Flask, вас встретит очень простой пример приложения, в котором всего пять строк кода. Вместо того, чтобы повторять этот тривиальный пример, я собираюсь показать вам немного более сложный пример, который даст вам хорошую базовую структуру для написания более крупных приложений.
Приложение будет существовать в пакете. В Python подкаталог, содержащий __init__.py файл, считается пакетом и может быть импортирован. Когда вы импортируете пакет, выполняется __init__.py и определяет, какие объекты переменных пакет предоставляет внешнему миру.
Давайте создадим пакет с именем app
, в котором будет размещено приложение. Убедитесь, что вы находитесь в каталоге микроблога, а затем выполните следующую команду:
(venv) $ mkdir app
В файле __init__.py для пакета app
будет содержаться следующий код:
app/__init__.py: Экземпляр приложения Flask
from flask import Flask
app = Flask(__name__)
from app import routes
Приведенный выше код создает объект приложения как экземпляр класса Flask
, импортированный из пакета flask. Переменная __name__
, передаваемая классу Flask
, является предопределенной переменной Python, которой присваивается имя модуля, в котором она используется. Flask использует местоположение переданного здесь модуля в качестве отправной точки, когда ему нужно загрузить связанные ресурсы, такие как файлы шаблонов, о которых я расскажу в главе 2. Для всех практических целей передача __name__
почти всегда приводит к правильной настройке Flask. Затем приложение импортирует модуль routes
, который еще не существует.
Один аспект, который поначалу может показаться запутанным, заключается в том, что есть две названные сущности app
. Пакет app
определяется каталогом приложения и в коде файла init.py в инструкции from app import routes
. Переменная app
определена как экземпляр класса Flask
в коде init.py, что делает ее переменной пакета app
.
Еще одна особенность заключается в том, что модуль routes
импортируется внизу, а не вверху кода, как это делается всегда. Нижний импорт - это хорошо известное решение, позволяющее избежать циклического импорта, распространенной проблемы с приложениями Flask. Вы увидите, что модулю routes
необходимо импортировать переменную app
, определенную в этом файле, поэтому размещение одного из взаимных импортов внизу позволяет избежать ошибки, возникающей в результате взаимных ссылок между этими двумя файлами.
Примечание переводчика
Если во время инициализации модуля интерпретатор натыкается на импорт другого модуля, то он приостанавливает инициализацию файла до полного удовлетворения зависимости, тем самым весь оставшийся код модуля остается не загруженным. Проблема возникает когда модули ссылаются друг на друга, а именно на код, который ещё не загружен в интерпретатор. Если взаимного импорта не избежать, то должна быть определена строгая иерархия между модулями. В данной ситуации основной файл приложения должен быть полностью загружен первым.
Итак, что входит в модуль routes
? Маршруты обрабатывают разные URL-адреса, поддерживаемые приложением. В Flask обработчики маршрутов приложения записаны в виде функций Python, называемых функциями просмотра. Функции просмотра сопоставляются с одним или несколькими URL-адресами маршрута, так что Flask знает, какую логику выполнять, когда клиент запрашивает данный URL.
Вот первая функция просмотра для этого приложения, которую вам нужно написать в новом модуле с именем app/routes.py:
app/routes.py: Маршрут на главную страницу
from app import app
@app.route('/')
@app.route('/index')
def index():
return "Hello, World!"
Эта функция просмотра на самом деле довольно короткая, она просто возвращает приветствие в виде строки. Две странные строки @app.route
над функцией являются декораторами, уникальной особенностью языка Python. Декоратор изменяет функцию, которая следует за ним. Обычная схема с декораторами - использовать их для регистрации функций в качестве обратных вызовов для определенных событий. В этом случае декоратор @app.route
создает ассоциацию между URL, указанным в качестве аргумента, и функцией. В этом примере есть два декоратора, которые связывают URL-адреса /
и /index
с этой функцией. Это означает, что когда веб-браузер запрашивает любой из этих двух URL-адресов, Flask собирается вызвать эту функцию и передать возвращаемое значение обратно браузеру в качестве ответа. Если это еще не имеет полного смысла, то вскоре это станет понятно, когда вы запустите это приложение.
Для завершения работы приложения у вас должен быть код на Python верхнего уровня, который определяет экземпляр приложения Flask. Давайте назовем этот файл microblog.py и определим его как единственную строку, которая импортирует экземпляр приложения:
microblog.py: Основной модуль приложения
from app import app
Помните две сущности app
? Здесь вы можете увидеть обе вместе в одной строке. Экземпляр приложения Flask называется app
и является членом пакета app
. Инструкция from app import app
импортирует переменную app
, которая является членом пакета app
. Если вас это смущает, вы можете переименовать пакет или переменную во что-нибудь другое.
Просто чтобы убедиться, что вы все делаете правильно, ниже вы можете увидеть схему структуры проекта на данный момент:
microblog/
venv/
app/
__init__.py
routes.py
microblog.py
Хотите верьте, хотите нет, но эта первая версия приложения завершена! Однако перед ее запуском Flask необходимо объяснить, как ее импортировать, установив переменную среды FLASK_APP
:
(venv) $ export FLASK_APP=microblog.py
Если вы используете командную строку Microsoft Windows, то используйте set
вместо export
в приведенной выше команде.
Вы готовы удивиться? Вы можете запустить свое первое веб-приложение, набрав команду flask run
, как показано ниже:
(venv) $ flask run
Serving Flask app 'microblog.py' (lazy loading)
Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
Debug mode: off
Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Что здесь произошло? Команда flask run
будет искать экземпляр приложения Flask в модуле, на который ссылается переменная окружения FLASK_APP
, которая в данном случае является microblog.py. Команда настраивает веб-сервер, который настроен на пересылку запросов этому приложению.
После инициализации сервер будет ожидать подключения клиента. Вывод из flask run
указывает, что сервер работает по IP-адресу 127.0.0.1, который всегда является адресом вашего собственного компьютера. Этот адрес настолько распространен, что также имеет более простое название, которое вы, возможно, видели раньше: localhost. Сетевые серверы прослушивают соединения по определенному номеру порта. Приложения, развернутые на производственных веб-серверах, обычно прослушивают порт 443, а иногда и 80, если они не используют шифрование, но для доступа к этим портам требуются права администратора. Поскольку это приложение запущено в среде разработки, Flask использует порт 5000. Теперь откройте свой веб-браузер и введите следующий URL в поле адреса:
http://localhost:5000/
В качестве альтернативы вы можете использовать этот другой URL:
http://localhost:5000/index
Вы видите сопоставления маршрутов приложения в действии? Первый URL соответствует /
, а второй - /index
. Оба маршрута связаны с единственной функцией просмотра в приложении, поэтому они выдают один и тот же результат, который представляет собой строку, возвращаемую функцией. Если вы введете любой другой URL, вы получите сообщение об ошибке, поскольку приложение распознает только эти два URL.
![](https://habrastorage.org/getpro/habr/upload_files/bb3/ba7/30d/bb3ba730da5178c36b0b756aab9cfd6d.png)
Когда вы закончите играть с сервером, вы можете просто нажать Ctrl-C, чтобы остановить его.
Поздравляем, вы сделали первый важный шаг к тому, чтобы стать веб-разработчиком!
У вас возникли проблемы с запуском приложения Flask? На большинстве компьютеров доступен порт 5000, но есть вероятность, что на вашем компьютере уже запущено приложение, использующее этот порт, и в этом случае flask run
команда завершится ошибкой с сообщением "адрес уже используется" или аналогичной ошибкой. Если вы используете компьютер Macintosh, некоторые версии macOS запускают службу под названием "Airplay Receiver" на этом порту. Если вы не можете понять, как удалить программное обеспечение, использующее порт 5000, вы можете попробовать запустить Flask на другом порту. Например, вот как запустить сервер на порту 5001:
(venv) $ flask run --port 5001
Примечание переводчика
Если вы попробовали вывести «Привет мир!» или другую надпись на русском и у вас возникла проблема с кодировкой, то проверьте кодировку файла, она должна быть «UTF-8», если нет, то пересохраните явно указав её. Если вы работаете в IDE и создаёте файлы через неё, то в большинстве случаев будет правильная кодировка. Так же рекомендуется в начале каждого файла Python добавлять строку:
# -*- coding: utf-8 -*-
Прежде чем закончить эту главу, я покажу вам еще одну вещь. Поскольку переменные окружения не запоминаются во время сеансов терминала, вам может показаться утомительным постоянно устанавливать FLASK_APP
переменную окружения при открытии нового окна терминала для работы с вашим приложением Flask. Но, к счастью, Flask позволяет вам регистрировать переменные среды, которые вы хотите использовать автоматически при запуске flask
команды. Чтобы использовать эту опцию, вам необходимо установить пакет python-dotenv:
(venv) $ pip install python-dotenv
Теперь вы можете просто записать имя переменной среды и значение в файл с именем .flaskenv, расположенный в каталоге верхнего уровня проекта:
.flaskenv: Переменные среды для команды flask
FLASK_APP=microblog.py
Команда flask
выполнит поиск файла .flaskenv и импортирует все переменные, определенные в нем, точно так, как если бы они были определены в среде.