Applications Streamlit multi-pages
Structure et navigation pour les apps avec plusieurs pages.
Structure du répertoire
streamlit_app.py # Point d'entrée principal
app_pages/
home.py
analytics.py
settings.py
Important : Nommez votre répertoire de pages app_pages/ (et non pages/). L'utilisation de pages/ entre en conflit avec l'ancienne API de découverte automatique de Streamlit et peut causer des comportements inattendus.
Module principal
# streamlit_app.py
import streamlit as st
# Initialiser l'état global (partagé entre les pages)
if "api_client" not in st.session_state:
st.session_state.api_client = init_api_client()
# Définir la navigation
page = st.navigation([
st.Page("app_pages/home.py", title="Home", icon=":material/home:"),
st.Page("app_pages/analytics.py", title="Analytics", icon=":material/bar_chart:"),
st.Page("app_pages/settings.py", title="Settings", icon=":material/settings:"),
])
# L'interface au niveau de l'app s'exécute avant le contenu de la page
# Utile pour les éléments partagés comme les titres
st.title(f"{page.icon} {page.title}")
page.run()
Note : Quand vous gérez les titres dans streamlit_app.py, les pages individuelles ne doivent PAS utiliser st.title à nouveau.
Position de la navigation
Peu de pages (3-7) → Navigation en haut :
page = st.navigation([...], position="top")
Crée un menu horizontal épuré. Parfait pour les apps simples. Les sections sont supportées aussi—elles apparaissent comme des menus déroulants dans la nav du haut.
Nombreuses pages ou sections imbriquées → Sidebar :
page = st.navigation({
"Main": [
st.Page("app_pages/home.py", title="Home"),
st.Page("app_pages/analytics.py", title="Analytics"),
],
"Admin": [
st.Page("app_pages/settings.py", title="Settings"),
st.Page("app_pages/users.py", title="Users"),
],
}, position="sidebar")
Mixte : Certaines pages non groupées :
Utilisez une clé chaîne vide "" pour les pages qui ne doivent pas être dans une section. Ces pages non groupées apparaissent toujours en premier, avant tout groupe nommé. Mettez toutes les pages non groupées dans une seule clé "" :
page = st.navigation({
"": [
st.Page("app_pages/home.py", title="Home"),
st.Page("app_pages/about.py", title="About"),
],
"Analytics": [
st.Page("app_pages/dashboard.py", title="Dashboard"),
st.Page("app_pages/reports.py", title="Reports"),
],
}, position="top")
Modules de pages
# app_pages/analytics.py
import streamlit as st
# Accéder à l'état global
api = st.session_state.api_client
user = st.session_state.user
# Contenu spécifique à la page (le titre est géré dans streamlit_app.py)
data = api.fetch_analytics(user.id)
st.line_chart(data)
État global
Initialisez l'état dans le module principal seulement s'il est nécessaire sur plusieurs pages :
# streamlit_app.py
st.session_state.api = init_client()
st.session_state.user = get_user()
st.session_state.settings = load_settings()
Conseil : Utilisez st.session_state.setdefault("key", default_value) pour initialiser les valeurs seulement si elles n'existent pas.
Pourquoi le module principal (pour l'état global) :
- S'exécute avant chaque page
- Garantit que l'état est initialisé
- Source unique de vérité
État spécifique à une page
Utilisez des clés préfixées pour l'état spécifique à une page :
# app_pages/analytics.py
if "analytics_date_range" not in st.session_state:
st.session_state.analytics_date_range = default_range()
Partager des éléments entre les pages
Mettez l'interface partagée au point d'entrée (avant page.run()) pour qu'elle apparaisse sur toutes les pages :
# streamlit_app.py
import streamlit as st
pages = [...]
page = st.navigation(pages)
# Titre partagé
st.title(f"{page.icon} {page.title}")
# Widgets de sidebar partagés
with st.sidebar:
st.selectbox("Theme", ["Light", "Dark"])
page.run()
Navigation programmatique
Naviguer vers une autre page par programme :
if st.button("Go to Settings"):
st.switch_page("app_pages/settings.py")
Créer des liens de navigation avec st.page_link :
st.page_link("app_pages/home.py", label="Home", icon=":material/home:")
st.page_link("https://example.com", label="External", icon=":material/open_in_new:")
Note : Préférez
st.navigationàst.page_linkpour la navigation standard. N'utilisez passt.page_linkpour recréer la barre de nav que vous obtenez avecst.navigation. N'utilisezst.page_linkque quand vous liez vers des pages depuis ailleurs que la sidebar, ou quand vous construisez un menu de navigation plus complexe.
Pages conditionnelles
Montrez différentes pages selon le rôle de l'utilisateur, l'authentification, ou toute autre condition en construisant la liste des pages dynamiquement :
# streamlit_app.py
import streamlit as st
pages = [st.Page("app_pages/home.py", title="Home", icon=":material/home:")]
if st.user.is_logged_in:
pages.append(st.Page("app_pages/dashboard.py", title="Dashboard", icon=":material/bar_chart:"))
if st.session_state.get("is_admin"):
pages.append(st.Page("app_pages/admin.py", title="Admin", icon=":material/settings:"))
page = st.navigation(pages)
page.run()
Conditions courantes pour afficher/masquer des pages :
st.user.is_logged_inpour les utilisateurs authentifiés- Flags
st.session_state(rôles, permissions, feature flags) - Variables d'environnement ou secrets
- Accès basé sur le temps (ex. : fonctionnalités bêta)
Imports depuis les pages
Quand vous importez depuis des fichiers de pages dans app_pages/, toujours importer depuis la perspective du répertoire racine :
# app_pages/dashboard.py - BON
from utils.data import load_sales_data
# app_pages/dashboard.py - MAUVAIS (n'utilisez pas d'imports relatifs)
from ..utils.data import load_sales_data