Данные в видео:
product,price,category,month
Laptop,1200,Electronics,January
Phone,800,Electronics,January
Chair,150,Furniture,February
Table,300,Furniture,March
Camera,600,Electronics,March
TV,1400,Electronics,April
Sofa,900,Furniture,April
К этому моменту наше приложение уже умеет довольно много. Мы загрузили данные, добавили фильтры, построили графики и сделали dashboard интерактивным. Но появляется новая проблема — приложение начинает разрастаться.
Сначала всё выглядит довольно удобно: один файл, несколько filters, пара графиков и таблица. Но чем больше логики появляется в проекте, тем сложнее становится ориентироваться в коде.
В какой-то момент один app.py превращается в огромный файл, где перемешаны таблицы, filters, графики, настройки и обработка данных. Именно поэтому практически любое серьёзное Streamlit-приложение рано или поздно становится многостраничным.
Например, в одном разделе dashboard может находиться общая аналитика, в другом — графики, в третьем — сырые данные, а в четвёртом — настройки или загрузка файлов. И здесь появляется ещё одна важная тема — состояние приложения.
Представьте ситуацию: пользователь выбрал категорию товара на одной странице, а затем перешёл на другую. Было бы странно, если бы выбранные данные внезапно исчезли. Для решения таких задач Streamlit предоставляет session_state.
Что вы узнаете в рамках статьи
В этом уроке мы разберём, как организовывать большие Streamlit-проекты и разделять приложение на несколько страниц.
Вы научитесь:
- создавать многостраничные dashboards;
- работать с папкой
pages; - передавать данные между страницами;
- сохранять пользовательское состояние;
- использовать
session_state; - и строить более структурированные Streamlit-приложения.
К концу урока наш dashboard станет намного ближе к настоящему production-приложению.
Ключевые термины
- Многостраничное приложение — приложение, состоящее из нескольких отдельных страниц.
pages— специальная папка Streamlit для автоматического создания страниц.session_state— объект Streamlit для хранения данных между перезапусками приложения.- Состояние приложения — данные, которые сохраняются во время работы пользователя с интерфейсом.
- Session — пользовательская сессия приложения.
Почему большие Streamlit-приложения начинают “ломаться”
Почти каждый Streamlit-проект проходит одинаковый путь.
Сначала приложение выглядит очень аккуратно:
st.title("Dashboard")
st.dataframe(df)
Потом появляются filters, графики, sidebar, загрузка файлов, таблицы и дополнительные настройки. И через некоторое время файл начинает занимать уже сотни строк. Читать такой код становится тяжело. А добавлять новые функции — ещё тяжелее. Именно поэтому Streamlit поддерживает многостраничность.
Папка pages
В Streamlit многостраничные приложения создаются очень просто.
Предположим, сейчас структура проекта выглядит так:
project/
│
├── app.py
├── sales.csv
Создадим папку pages и добавим в нее новые файлы:
project/
│
├── app.py
├── sales.csv
│
├── pages/
│ ├── analytics.py
│ ├── charts.py
│ └── raw_data.py
И вот здесь происходит очень приятная магия Streamlit. После запуска приложения все файлы из папки pages автоматически превращаются в отдельные страницы dashboard.
Создаём первую дополнительную страницу
Например, файл pages/charts.py может содержать:
import streamlit as st
st.title("Графики")
А файл pages/raw_data.py может отображать таблицу:
import streamlit as st
import pandas as pd
df = pd.read_csv("sales.csv")
st.title("Сырые данные")
st.dataframe(df)
После запуска приложения в sidebar автоматически появится навигация между страницами.
Проблема состояния
Теперь представим ситуацию. Пользователь выбрал категорию, настроил filters и открыл страницу графиков. А затем перешёл на другую страницу — и всё сбросилось. Это одна из самых частых проблем у новичков в Streamlit. Причина в том, что Streamlit постоянно перезапускает script приложения. Именно поэтому обычные переменные не подходят для хранения пользовательского состояния.
Что такое session_state
Для решения этой проблемы Streamlit предоставляет session_state. Он работает как специальное хранилище данных внутри пользовательской сессии.
Например:
st.session_state["category"] = "Electronics"
Теперь значение сохранится даже после rerun, перехода между страницами и обновления widgets.
Сохраняем выбранную категорию
Предположим, у нас есть selectbox:
category = st.selectbox(
"Категория",
df["category"].unique()
)
Теперь сохраним значение:
st.session_state["category"] = category
На другой странице можно получить доступ к этим данным:
selected_category = st.session_state["category"]
st.write(selected_category)
И вот теперь dashboard начинает ощущаться как единое приложение, а не набор отдельных страниц.
Проверяем наличие данных
Но здесь есть важный момент. Если пользователь впервые открыл страницу, нужного значения может ещё не существовать. Поэтому обычно делают проверку:
if "category" not in st.session_state:
st.session_state["category"] = "Electronics"
Такой подход помогает избежать ошибок.
Создаём структуру dashboard
Теперь наше приложение уже можно разделить логически.
Например:
app.py— главная страница;analytics.py— аналитика;charts.py— графики;raw_data.py— таблицы.
Это делает проект более понятным, масштабируемым и удобным для поддержки. Именно так обычно и организуют большие Streamlit-dashboard.
Как выглядит приложение теперь
До этого у нас был один большой файл. Теперь dashboard превращается в набор отдельных страниц, между которыми пользователь может перемещаться через navigation sidebar. При этом состояние приложения сохраняется, а данные становятся доступными из разных частей проекта. Именно на этом этапе Streamlit-приложение начинает выглядеть как полноценный web-инструмент.
Наиболее частые ошибки
- Файл не появляется в navigation sidebar
Обычно проблема в том, что файл находится не внутри папкиpages. session_stateне сохраняет данные
Часто значение просто не записывается вsession_stateпосле изменения widget.- Ошибка при обращении к ключу
Если ключ ещё не существует, Streamlit может выдать ошибку. Обычно это решают через проверкуif key not in st.session_state. - Слишком большой
app.py
Одна из самых частых проблем у новичков. Чем раньше приложение разбивается на страницы, тем проще становится поддержка проекта.
Наиболее частые вопросы
- Можно ли создавать много уровней страниц?
Streamlit поддерживает вложенную организацию файлов, но чаще всего dashboards делают достаточно плоскими и простыми. session_stateхранится после закрытия браузера?
Нет, состояние существует только внутри текущей пользовательской сессии.- Можно ли передавать DataFrame между страницами?
Да, черезsession_stateможно сохранять и таблицы Pandas. - Почему Streamlit автоматически создаёт navigation sidebar?
Framework сам анализирует папкуpagesи строит навигацию автоматически.
Итоги
Сегодня мы сделали ещё один очень важный шаг и превратили наш dashboard из одного большого файла в полноценное структурированное приложение. Мы познакомились с папкой pages, научились создавать многостраничные Streamlit-приложения и увидели, насколько легко framework позволяет организовывать navigation между разделами dashboard.
Кроме того, мы разобрались с session_state и научились сохранять пользовательское состояние между страницами. Это одна из важнейших тем в Streamlit, потому что именно состояние делает приложение “живым” и позволяет пользователю комфортно взаимодействовать с dashboard.
Теперь наше приложение уже начинает напоминать настоящий production-dashboard с несколькими страницами, общей логикой и сохранением пользовательских данных между разделами.