$ sudo teach IT

Данные в видео: 

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 с несколькими страницами, общей логикой и сохранением пользовательских данных между разделами.

На следующий урок