Создаем первое веб-приложение на Flask
Первое приложение на Flask умещается в один файл из семи строк и запускается одной командой. В уроке показано, как подготовить окружение, написать и запустить сервер, добавить несколько страниц с параметрами в адресе и вернуть ответ в HTML или JSON. Все примеры рассчитаны на Flask 3.x и Python 3.12.

Содержание статьи
Подготовка окружения и установка
Flask ставится из PyPI через pip. Чтобы зависимости проекта не смешивались с другими программами, сначала создайте виртуальное окружение в папке проекта.
mkdir hello_flask
cd hello_flask
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux и macOS
source .venv/bin/activate
pip install flask
flask --versionПоследняя команда выводит версии Python, Flask и Werkzeug. Если она сработала, установка прошла успешно. Вместе с Flask автоматически ставятся его зависимости: Werkzeug (обработка запросов), Jinja2 (шаблоны), Click (командная строка) и еще несколько пакетов. Подробнее о том, зачем нужны окружения и как ими управлять, рассказано в статье про виртуальные окружения Python.
Минимальное приложение
Создайте в папке проекта файл app.py. Не называйте его flask.py: тогда Python импортирует ваш файл вместо библиотеки, и программа упадет с непонятной ошибкой.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "<h1>Привет, Flask!</h1><p>Первое приложение работает.</p>"
if __name__ == "__main__":
app.run(debug=True)Разберем по строкам:
Flask(__name__)создает объект приложения. Имя модуля нужно, чтобы Flask нашел рядом папки с шаблонами и статикой.@app.route("/")связывает адрес с функцией. Это обычный декоратор, принцип работы которых описан в статье о декораторах.- Функция
index()называется представлением (view). Ее возвращаемое значение Flask отправляет браузеру как тело ответа. - Блок
if __name__ == "__main__"запускает встроенный сервер, только когда файл выполняется напрямую.
Запуск сервера разработки
Запустить приложение можно двумя способами. Оба поднимают сервер по адресу http://127.0.0.1:5000/.
python app.py
# или через команду flask
flask --app app run --debugОткройте адрес в браузере, и появится заголовок из функции index(). Остановить сервер можно сочетанием Ctrl+C в терминале. Если файл называется app.py или wsgi.py, параметр --app можно не указывать.
| Опция | Что делает |
|---|---|
--debug | Перезапускает сервер при изменении кода и показывает подробную страницу ошибки |
--port 8000 | Меняет порт, если 5000 занят другой программой |
--host 0.0.0.0 | Открывает доступ с других устройств локальной сети |
Режим отладки позволяет выполнять код прямо из браузера на странице ошибки, поэтому на рабочем сервере его никогда не включают. Встроенный сервер тоже предназначен только для разработки; в продакшене приложение запускают через WSGI-сервер вроде Gunicorn или Waitress.
Маршруты и представления
Каждая страница сайта это пара: адрес в декораторе и функция, которая формирует ответ. Маршрутов может быть сколько угодно, но имена функций не должны повторяться.
Несколько страниц
Для ссылок между страницами удобна функция url_for(): она строит адрес по имени представления, поэтому при смене пути в декораторе ссылки обновятся сами.
from flask import Flask, url_for
app = Flask(__name__)
@app.route("/")
def index():
return f'<a href="{url_for("about")}">О проекте</a>'
@app.route("/about/")
def about():
return "Учебный проект на Flask"Обратите внимание на слеш в конце /about/. Если он указан в маршруте, запрос на /about автоматически перенаправится на адрес со слешем. Если слеша в маршруте нет, адрес со слешем вернет ошибку 404.
Переменные в адресе
Часть пути можно сделать переменной, заключив ее в угловые скобки. Значение передается в функцию как аргумент. Конвертер перед именем проверяет и преобразует тип.
from flask import Flask
from markupsafe import escape
app = Flask(__name__)
@app.route("/user/<name>")
def user(name):
return f"Профиль пользователя {escape(name)}"
@app.route("/post/<int:post_id>")
def post(post_id):
return f"Статья номер {post_id}, следующая {post_id + 1}"Адрес /post/abc не совпадет с маршрутом, и Flask вернет 404 без вызова функции. Доступны конвертеры string (по умолчанию), int, float, path (строка со слешами) и uuid. Функция escape() защищает от внедрения HTML, если значение из адреса выводится в страницу.
Методы GET и POST
По умолчанию маршрут отвечает только на GET-запросы. Чтобы принимать данные из форм, методы перечисляют явно и проверяют request.method.
from flask import Flask, request
app = Flask(__name__)
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
return f"Привет, {request.form.get('name', 'гость')}"
return '<form method="post"><input name="name"><button>Войти</button></form>'Полноценная работа с формами, валидацией и защитой от CSRF описана в уроке про формы во Flask.
Что может вернуть представление
Кроме строки, функция может вернуть словарь или список, и Flask сам превратит их в JSON с нужным заголовком. Вторым элементом кортежа указывается код ответа.
from flask import Flask
app = Flask(__name__)
@app.route("/api/status")
def status():
return {"status": "ok", "version": 1}
@app.route("/secret")
def secret():
return "Доступ запрещен", 403Писать HTML внутри строк Python неудобно уже на второй странице. Для разметки используют шаблоны Jinja2 и функцию render_template(), а файлы шаблонов кладут в папку templates рядом с app.py. Как устроен шаблон и наследование блоков, показано в статье о создании шаблона Flask. Все возможности маршрутизации собраны в разделе Quickstart официальной документации.
Частые вопросы
Короткие ответы на проблемы, с которыми сталкиваются при первом запуске.
Почему изменения в коде не видны в браузере?
Сервер запущен без режима отладки, и код не перезагружается. Запустите его с флагом --debug или перезапустите вручную после каждого изменения.
Что делать, если порт 5000 занят?
Укажите другой порт: flask --app app run --port 8000 или app.run(port=8000). На macOS порт 5000 часто занимает служба AirPlay Receiver.
Можно ли открыть приложение с телефона?
Да, если телефон в той же сети. Запустите сервер с --host 0.0.0.0 и откройте в браузере телефона IP-адрес компьютера с портом, например http://192.168.1.10:5000.
Чем Flask отличается от Django?
Flask дает только ядро: маршрутизацию, запросы и шаблоны. База данных, авторизация и формы подключаются расширениями по мере необходимости. Django включает все это сразу, поэтому для небольших сервисов и обучения Flask обычно проще.