文章目录
- [动态导航菜单(st.navigation / st.Page)](#动态导航菜单(st.navigation / st.Page))
-
- [1.1 功能概述](#1.1 功能概述)
-
- [1.1.1 组件简介](#1.1.1 组件简介)
- [1.1.2 核心应用场景](#1.1.2 核心应用场景)
- [1.1.3 版本前置要求](#1.1.3 版本前置要求)
- [1.2 核心两个API介绍](#1.2 核心两个API介绍)
-
- [1.2.1 st.Page:页面封装对象](#1.2.1 st.Page:页面封装对象)
-
- [1.2.1.1 两种创建方式](#1.2.1.1 两种创建方式)
- [1.2.1.2 关键参数](#1.2.1.2 关键参数)
- [1.2.2 st.navigation:导航菜单生成器](#1.2.2 st.navigation:导航菜单生成器)
-
- [1.2.2.1 入参格式](#1.2.2.1 入参格式)
- [1.3 完整权限动态导航开发流程(教程示例)](#1.3 完整权限动态导航开发流程(教程示例))
-
- [1.3.1 步骤1:初始化项目目录与页面文件](#1.3.1 步骤1:初始化项目目录与页面文件)
- [1.3.2 步骤2:会话状态全局初始化](#1.3.2 步骤2:会话状态全局初始化)
- [1.3.3 步骤3:定义函数式登录/登出页面](#1.3.3 步骤3:定义函数式登录/登出页面)
- [1.3.4 步骤4:批量创建所有Page页面对象](#1.3.4 步骤4:批量创建所有Page页面对象)
- [1.3.5 步骤5:根据角色动态组装页面分组字典](#1.3.5 步骤5:根据角色动态组装页面分组字典)
- [1.3.6 步骤6:渲染导航并执行页面](#1.3.6 步骤6:渲染导航并执行页面)
- [1.4 核心特性总结](#1.4 核心特性总结)
- [1.5 完整示例代码](#1.5 完整示例代码)
动态导航菜单(st.navigation / st.Page)
1.1 功能概述
1.1.1 组件简介
st.navigation 与 st.Page 是 Streamlit 1.36.0 新增的多页面应用API,用于动态生成侧边栏导航菜单 。
每次页面重运行时可更新页面列表,实现基于用户角色、权限的动态菜单渲染,适配权限管控、按需展示菜单等业务场景。
1.1.2 核心应用场景
- 搭建权限系统:不同角色(访客/普通用户/管理员)看到不同导航页面;
- 动态加载菜单:根据业务数据、登录状态增减导航条目;
- 自定义多页面分组:对页面进行分类分组,侧边栏生成菜单分区标题。
1.1.3 版本前置要求
python
# Streamlit 最低版本限制
streamlit >= 1.36.0
1.2 核心两个API介绍
1.2.1 st.Page:页面封装对象
用于封装单个页面,支持本地py文件页面、函数式页面两种定义方式,可配置标题、图标、是否设为默认首页。
1.2.1.1 两种创建方式
- 文件页面(项目py文件)
python
# 参数:文件路径、菜单标题、侧边栏图标、是否默认首页
settings_page = st.Page(
"settings.py",
title="账号设置",
icon=":material/settings:",
default=False
)
- 函数页面(当前脚本内定义函数,如登录、登出页)
python
def login():
st.header("用户登录")
role = st.selectbox("选择角色", [None, "Requester", "Responder", "Admin"])
if st.button("登录"):
st.session_state.role = role
st.rerun()
# 封装登录函数为页面
login_page = st.Page(login, title="登录页")
1.2.1.2 关键参数
title:侧边栏菜单显示名称;icon:Material图标标识,美化侧边栏;default:布尔值,当前用户进入应用时默认打开该页面。
1.2.2 st.navigation:导航菜单生成器
接收分组页面字典 ,自动渲染侧边栏分组导航菜单,返回导航实例,调用 .run() 执行当前选中页面。
1.2.2.1 入参格式
字典结构:{"分组标题": [页面对象列表]},字典的键对应侧边栏菜单分区标题,值为该分组下所有st.Page对象。
python
# 页面分组字典示例
page_groups = {
"账号管理": [logout_page, settings_page],
"需求模块": [request_1, request_2]
}
# 生成导航菜单
nav = st.navigation(page_groups)
# 运行当前选中页面
nav.run()
1.3 完整权限动态导航开发流程(教程示例)
1.3.1 步骤1:初始化项目目录与页面文件
- 项目入口文件:
streamlit_app.py(程序启动文件); - 独立页面文件:
settings.py、分角色文件夹admin/、request/、respond/存放角色专属页面; - 静态资源文件夹:
images/存放logo图片。
1.3.2 步骤2:会话状态全局初始化
在入口文件初始化登录角色,用于权限判断:
python
# 初始化角色会话状态,None=未登录访客
if "role" not in st.session_state:
st.session_state.role = None
# 定义全部可用角色
ROLES = [None, "Requester", "Responder", "Admin"]
1.3.3 步骤3:定义函数式登录/登出页面
python
# 登录页面函数
def login():
st.header("登录")
selected_role = st.selectbox("选择你的角色", ROLES)
if st.button("确认登录"):
st.session_state.role = selected_role
st.rerun()
# 登出页面函数
def logout():
# 清空角色并重跑,直接跳转登录页
st.session_state.role = None
st.rerun()
1.3.4 步骤4:批量创建所有Page页面对象
- 账号通用页面(所有登录用户可见)
python
logout_page = st.Page(logout, title="退出登录", icon=":material/logout:")
settings_page = st.Page("settings.py", title="账号设置", icon=":material/settings:")
account_pages = [logout_page, settings_page]
- 分角色业务页面
python
# 需求方页面
request_1 = st.Page("request/request_1.py", title="需求提交1", default=(st.session_state.role == "Requester"))
request_pages = [request_1, ...]
# 响应方页面
respond_pages = [...]
# 管理员页面
admin_pages = [...]
1.3.5 步骤5:根据角色动态组装页面分组字典
根据st.session_state.role的值,动态筛选该角色允许访问的页面,组装分组字典:
python
page_dict = {}
current_role = st.session_state.role
# 按角色填充对应业务页面分组
if current_role in ["Requester", "Admin"]:
page_dict["需求管理"] = request_pages
if current_role in ["Responder", "Admin"]:
page_dict["处理响应"] = respond_pages
if current_role == "Admin":
page_dict["管理员后台"] = admin_pages
# 所有登录用户都展示账号分组页面
if len(page_dict) > 0:
page_dict = {"账号中心": account_pages} | page_dict
1.3.6 步骤6:渲染导航并执行页面
区分未登录访客 与已登录用户两种逻辑:
python
# 全局通用顶部Logo(所有页面共享)
st.logo("images/horizontal_blue.png", icon_image="images/icon_blue.png")
st.title("需求管理系统")
# 未登录:仅展示登录页面
if not page_dict:
nav = st.navigation([st.Page(login)])
# 已登录:渲染动态分组菜单
else:
nav = st.navigation(page_dict)
# 执行当前选中的页面
nav.run()
1.4 核心特性总结
- 权限动态渲染:基于会话状态、用户角色实时筛选菜单,实现细粒度权限控制;
- 菜单分组管理:通过字典键实现侧边栏菜单分区,页面分类清晰;
- 双类型页面支持:同时支持外部文件页面、脚本内函数页面(登录/弹窗页);
- 全局共享元素 :入口文件中定义的
st.logo()、st.title()会在所有页面顶部统一展示; - 默认首页配置 :通过
default参数为不同角色设置专属默认打开页面; - 轻量化多页面 :替代传统
pages/文件夹静态多页面,菜单完全代码可控,无需固定目录结构。
1.5 完整示例代码
python
import streamlit as st
# 初始化角色会话状态,None=未登录访客
if "role" not in st.session_state:
st.session_state.role = None
# 定义全部可用角色
ROLES = [None, "Requester", "Responder", "Admin"]
# 登录页面函数
def login():
st.header("登录")
selected_role = st.selectbox("选择你的角色", ROLES)
if st.button("确认登录"):
st.session_state.role = selected_role
st.rerun()
# 登出页面函数
def logout():
# 清空角色并重跑,直接跳转登录页
st.session_state.role = None
st.rerun()
logout_page = st.Page(logout, title="退出登录", icon=":material/logout:")
settings_page = st.Page("settings.py", title="账号设置", icon=":material/settings:")
account_pages = [logout_page, settings_page]
# 需求方页面
request_1 = st.Page("request/request_1.py", title="需求提交1", default=(st.session_state.role == "Requester"))
request_pages = [request_1, ...]
# 响应方页面
respond_pages = [...]
# 管理员页面
admin_pages = [...]
page_dict = {}
current_role = st.session_state.role
# 按角色填充对应业务页面分组
if current_role in ["Requester", "Admin"]:
page_dict["需求管理"] = request_pages
if current_role in ["Responder", "Admin"]:
page_dict["处理响应"] = respond_pages
if current_role == "Admin":
page_dict["管理员后台"] = admin_pages
# 所有登录用户都展示账号分组页面
if len(page_dict) > 0:
page_dict = {"账号中心": account_pages} | page_dict
# 全局通用顶部Logo(所有页面共享)
st.logo("images/horizontal_blue.png", icon_image="images/icon_blue.png")
st.title("需求管理系统")
# 未登录:仅展示登录页面
if not page_dict:
nav = st.navigation([st.Page(login)])
# 已登录:渲染动态分组菜单
else:
nav = st.navigation(page_dict)
# 执行当前选中的页面
nav.run()