0% found this document useful (0 votes)
12 views

Docs.streamlit.io-create a Dynamic Navigation Menu

This document provides a tutorial on creating a dynamic navigation menu in a multipage Streamlit app using st.navigation and st.Page, introduced in version 1.36.0. It outlines the prerequisites, including the need for Streamlit 1.36.0 and a basic understanding of the relevant functions, and details the implementation steps for user role-based navigation. The tutorial includes code snippets and a directory structure for organizing the app's files, enabling users to customize their navigation based on their roles as Requester, Responder, or Admin.

Uploaded by

oraculosia
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

Docs.streamlit.io-create a Dynamic Navigation Menu

This document provides a tutorial on creating a dynamic navigation menu in a multipage Streamlit app using st.navigation and st.Page, introduced in version 1.36.0. It outlines the prerequisites, including the need for Streamlit 1.36.0 and a basic understanding of the relevant functions, and details the implementation steps for user role-based navigation. The tutorial includes code snippets and a directory structure for organizing the app's files, enabling users to customize their navigation based on their roles as Requester, Responder, or Admin.

Uploaded by

oraculosia
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

Create a dynamic navigation menu

docs.streamlit.io/develop/tutorials/multipage/dynamic-navigation

Documentation

search
Search

st.navigation makes it easy to build dynamic navigation menus. You can change
the set of pages passed to st.navigation with each rerun, which changes the
navigation menu to match. This is a convenient feature for creating custom, role-
based navigation menus.

This tutorial uses st.navigation and st.Page, which were introduced in Streamlit
version 1.36.0. For an older workaround using the pages/ directory and
st.page_link, see Build a custom navigation menu with st.page_link.

Applied concepts

Use st.navigation and st.Page to define a multipage app.


Create a dynamic, role-based navigation menu.

1/8
Prerequisites

The following must be installed in your Python environment:

streamlit>=1.36.0

You should have a clean working directory called your-repository.

You should have a basic understanding of st.navigation and st.Page.

Summary

In this example, we'll build a dynamic navigation menu for a multipage app that
depends on the current user's role. You'll abstract away the use of username and
credentials to simplify the example. Instead, you'll use a selectbox to let users
choose a role and log in.

The entrypoint file, streamlit_app.py will handle user authentication. The other
pages will be stubs representing account management (settings.py) and specific
pages associated to three roles: Requester, Responder, and Admin. Requesters can
access the account and request pages. Responders can access the account and
respond pages. Admins can access all pages.

Here's a look at what we'll build:

Complete codeexpand_more
Directory structure:

your-repository/ ├── admin │ ├── admin_1.py │ └── admin_2.py ├── images


│ ├── horizontal_blue.png │ └── icon_blue.png ├── request │ ├──
request_1.py │ └── request_2.py ├── respond │ ├── respond_1.py │ └──
respond_2.py ├── settings.py └── streamlit_app.py

streamlit_app.py:

import streamlit as st if "role" not in st.session_state:


st.session_state.role = None ROLES = [None, "Requester", "Responder",
"Admin"] def login(): st.header("Log in") role = st.selectbox("Choose
your role", ROLES) if st.button("Log in"): st.session_state.role = role
st.rerun() def logout(): st.session_state.role = None st.rerun() role =
st.session_state.role logout_page = st.Page(logout, title="Log out",
icon=":material/logout:") settings = st.Page("settings.py",

2/8
title="Settings", icon=":material/settings:") request_1 = st.Page(
"request/request_1.py", title="Request 1", icon=":material/help:",
default=(role == "Requester"), ) request_2 = st.Page(
"request/request_2.py", title="Request 2", icon=":material/bug_report:"
) respond_1 = st.Page( "respond/respond_1.py", title="Respond 1",
icon=":material/healing:", default=(role == "Responder"), ) respond_2 =
st.Page( "respond/respond_2.py", title="Respond 2",
icon=":material/handyman:" ) admin_1 = st.Page( "admin/admin_1.py",
title="Admin 1", icon=":material/person_add:", default=(role ==
"Admin"), ) admin_2 = st.Page("admin/admin_2.py", title="Admin 2",
icon=":material/security:") account_pages = [logout_page, settings]
request_pages = [request_1, request_2] respond_pages = [respond_1,
respond_2] admin_pages = [admin_1, admin_2] st.title("Request manager")
st.logo("images/horizontal_blue.png",
icon_image="images/icon_blue.png") page_dict = {} if
st.session_state.role in ["Requester", "Admin"]: page_dict["Request"] =
request_pages if st.session_state.role in ["Responder", "Admin"]:
page_dict["Respond"] = respond_pages if st.session_state.role ==
"Admin": page_dict["Admin"] = admin_pages if len(page_dict) > 0: pg =
st.navigation({"Account": account_pages} | page_dict) else: pg =
st.navigation([st.Page(login)]) pg.run()

Built with Streamlit🎈


Fullscreen open_in_new

Build the example

Initialize your app

1. In your_repository, create a file named streamlit_app.py.

2. In a terminal, change directories to your_repository and start your app.

streamlit run streamlit_app.py

Your app will be blank since you still need to add code.

3. In streamlit_app.py, write the following:

import streamlit as st

3/8
4. Save your streamlit_app.py file and view your running app.

5. Click "Always rerun" or hit your "A" key in your running app.

Your running preview will automatically update as you save changes to


streamlit_app.py. Your preview will still be blank. Return to your code.

Add your page and image files

1. In your_repositoy, create a file named settings.py.

2. In settings.py add the following stub.

import streamlit as st st.header("Settings") st.write(f"You are


logged in as {st.session_state.role}.")

In later steps, you'll create an authentication method that saves the current
user's role to st.session_state.role. Since you'll be blocking access to this
page until a user is logged in, you don't need to initialize the "role" key in
Session State for this page.

3. Create similar stubs by changing the value of st.header for the following six
pages:

your-repository/ ├── admin │ ├── admin_1.py │ └── admin_2.py ├──


request │ ├── request_1.py │ └── request_2.py └── respond ├──
respond_1.py └── respond_2.py

For example, admin/admin_1.py should be the following:

import streamlit as st st.header("Admin 1") st.write(f"You are


logged in as {st.session_state.role}.")

4. Create an images subdirectory in your-repository and add the following two


files:

horizontal_blue.png
icon_blue.png
You now have all the files needed to build your app.

Initialize global values

4/8
1. Return to streamlit_app.py and initialize "role" in Session State.

if "role" not in st.session_state: st.session_state.role = None

You will use this value to gatekeep access to your app. This represents the role
of the current, authenticated user.

2. Define the available roles.

ROLES = [None, "Requester", "Responder", "Admin"]

None is included as a role since that is the value corresponding to an


unauthenticated user.

Define your user authentication pages

st.navigation lets you define pages from Python functions. Here, you'll define the
login and logout pages from Python functions.

1. Begin your login page (function definition).

def login():

2. Add a header for the page.

st.header("Log in")

3. Create a selectbox for the user to choose a role.

role = st.selectbox("Choose your role", ROLES)

4. Add a button to commit the user role to Session State.

if st.button("Log in"): st.session_state.role = role st.rerun()

This is an abstraction of an authentication workflow. When a user clicks the


button, Streamlit saves the role to Session State and reruns the app. In later
steps, you'll add logic to direct users to a role's default page when the value
changes in st.session_state.role. This completes your login page function.

5. Begin your logout page (function definition).

def logout():

5/8
6. Immediately set the role to None and rerun the app.

st.session_state.role = None st.rerun()

Since the lougout page function immediately updates Session State and
reruns, a user will never view this page. The page will execute in a fraction of a
second and, upon rerunning, the app will send the user to the login page.
Therefore, no additional elements are rendered on the page. If desired, you
can change this page to also include a button, similar to the login page. A
button would allow users to confirm they really intend to log out.

Define all your pages

1. As a convenience, save st.session_state.role to a variable.

role = st.session_state.role

2. Define your account pages.

logout_page = st.Page(logout, title="Log out",


icon=":material/logout:") settings = st.Page("settings.py",
title="Settings", icon=":material/settings:")

This gives each page a nice title and icon to make your navigation menu look
neat and clean.

3. Define your request pages.

request_1 = st.Page( "request/request_1.py", title="Request 1",


icon=":material/help:", default=(role == "Requester"), ) request_2
= st.Page( "request/request_2.py", title="Request 2",
icon=":material/bug_report:" )

If you don't manually declare a default page in st.navigation, then the first
page will automatically be the default. The first page in the menu will be "Log
out" within an "Account" section of the menu. Therefore, you'll need to tell
Streamlit what page each user should be directed to by default.

This code dynamically sets default=True when the role is "Requester" and
sets it to False, otherwise.

6/8
4. Define your remaining pages.

respond_1 = st.Page( "respond/respond_1.py", title="Respond 1",


icon=":material/healing:", default=(role == "Responder"), )
respond_2 = st.Page( "respond/respond_2.py", title="Respond 2",
icon=":material/handyman:" ) admin_1 = st.Page(
"admin/admin_1.py", title="Admin 1", icon=":material/person_add:",
default=(role == "Admin"), ) admin_2 = st.Page("admin/admin_2.py",
title="Admin 2", icon=":material/security:")

Similar to the request pages, the default parameter is set for the other roles'
default pages.

5. Group your pages into convenient lists.

account_pages = [logout_page, settings] request_pages =


[request_1, request_2] respond_pages = [respond_1, respond_2]
admin_pages = [admin_1, admin_2]

These are all the pages available to logged-in users.

Define your common elements and navigation

1. Add a title to show on all pages.

st.title("Request manager")

Since you're calling the title command in your entrypoint file, this title will be
visible on all pages. Elements created in your entrypoint file create a frame of
common elements around all your pages.

2. Add a logo to your app.

st.logo("images/horizontal_blue.png",
icon_image="images/icon_blue.png")

Once again, since you're calling this command in your entrypoint file, you won't
need to also call it within each page.

7/8
3. Initialize a dictionary of page lists.

page_dict = {}

In the next step, you'll check the user's role and add pages to the dictionary
that the user is allowed to access. When st.navigation receives a dictionary
of page lists, it creates a navigation menu with groups of pages and section
headers.

4. Build the dictionary of allowed pages by checking the user's role.

if st.session_state.role in ["Requester", "Admin"]:


page_dict["Request"] = request_pages if st.session_state.role in
["Responder", "Admin"]: page_dict["Respond"] = respond_pages if
st.session_state.role == "Admin": page_dict["Admin"] = admin_pages

5. Check if the user is allowed to access any pages and add the account pages if
they are.

if len(page_dict) > 0: pg = st.navigation({"Account":


account_pages} | page_dict)

If page_dict is not empty, then the user is logged in. The | operator merges
the two dictionaries, adding the account pages to the beginning.

6. Fallback to the login page if the user isn't logged in.

else: pg = st.navigation([st.Page(login)])

7. Execute the page returned by st.navigation.

pg.run()

8. Save your streamlit_app.py file and view your app!

Try logging in, switching pages, and logging out. Try again with a different role.

forum

Still have questions?

Our forums are full of helpful information and Streamlit experts.

8/8

You might also like