Skip to main content

A small package that allows you to create multi page streamlit apps

Project description

Streamlit Multipage

Simple Python package to implement multiple pages using streamlit.

pip install streamlit-multipage

Getting started

Simple single-page app

Given one streamlit app in a Python file like this:

import streamlit as st

st.title("My Amazing App")
name = st.text_input("Your Name: ")
st.write(f"Hello {name}!")

Wrap it into a function with a st parameter and arbitrary keyword arguments.

import streamlit as st
from streamlit_multipage import MultiPage


def my_page(st, **state):
    st.title("My Amazing App")
    name = st.text_input("Your Name: ")
    st.write(f"Hello {name}!")


app = MultiPage()
app.st = st

app.add_app("Hello World", my_page)

app.run()

This example is trivial and will not give any additional value. The next example will introduce state persistance.

Saving State

If the state should be persisted between re-runs (pressing R) o application runs (running streamlit run). The variables can be saved by calling the save function and accessed conveniently via the state dictionary.

import streamlit as st
from streamlit_multipage import MultiPage


def my_page(st, **state):
    st.title("My Amazing App")
    name_ = state["name"] if "name" in state else ""
    name = st.text_input("Your Name: ", value=name_)
    st.write(f"Hello {name}!")

    MultiPage.save({"name": name})


app = MultiPage()
app.st = st

app.add_app("Hello World", my_page)

app.run()

Multiple pages

When dealing with multiple pages, the workflow is the same. If reading, always sanitize the input and make sure the values are available and correct.

import streamlit as st
from streamlit_multipage import MultiPage


def input_page(st, **state):
    st.title("Body Mass Index")

    weight_ = state["weight"] if "weight" in state else 0.0
    weight = st.number_input("Your weight (Kg): ", value=weight_)

    height_ = state["height"] if "height" in state else 0.0
    height = st.number_input("Your height (m): ", value=height_)

    if height and weight:
        MultiPage.save({"weight": weight, "height": height})


def compute_page(st, **state):
    st.title("Body Mass Index")

    if "weight" not in state or "height" not in state:
        st.warning("Enter your data before computing. Go to the Input Page")
        return

    weight = state["weight"]
    height = state["height"]

    st.metric("BMI", round(weight / height ** 2, 2))


app = MultiPage()
app.st = st

app.add_app("Input Page", input_page)
app.add_app("BMI Result", compute_page)

app.run()

Using Namespaces

When handling multiple pages, it is possible to have variable name collisions, by default all variables are saved in a common namespace called global but it is also possible to defined custom namepsaces. One page can write to many namespaces at once.

import streamlit as st
from streamlit_multipage import MultiPage


def input_page(st, **state):
    namespace = "input"
    variables = state[namespace] if namespace in state else {}
    st.title("Tax Deduction")

    salary_ = variables["salary"] if "salary" in variables else 0.0
    salary = st.number_input("Your salary (USD): ", value=salary_)

    tax_percent_ = variables["tax_percent"] if "tax_percent" in variables else 0.0
    tax_percent = st.number_input("Taxes (%): ", value=tax_percent_)

    total = salary * (1 - tax_percent)

    if tax_percent and salary:
        MultiPage.save({"salary": salary, "tax_percent": tax_percent}, namespaces=[namespace])

    if total:
        MultiPage.save({"total": total}, namespaces=[namespace, "result"])


def compute_page(st, **state):
    namespace = "result"
    variables = state[namespace] if namespace in state else {}
    st.title("Your Salary After Taxes")

    if "total" not in variables:
        st.warning("Enter your data before computing. Go to the Input Page")
        return

    total = variables["total"]

    st.metric("Total", round(total, 2))


app = MultiPage()
app.st = st

app.add_app("Input Page", input_page)
app.add_app("Net Salary", compute_page)

app.run()

Automatic Namespaces

If the namespace is set to the same App name (first parameter of add_app) the state will be pre-filtered before sending it to the function.

import streamlit as st
from streamlit_multipage import MultiPage


def input_page(st, **state):
    st.title("Tax Deduction")

    salary_ = state["salary"] if "salary" in state else 0.0
    salary = st.number_input("Your salary (USD): ", value=salary_)

    tax_percent_ = state["tax_percent"] if "tax_percent" in state else 0.0
    tax_percent = st.number_input("Taxes (%): ", value=tax_percent_)

    total = salary * (1 - tax_percent)

    if tax_percent and salary:
        MultiPage.save({"salary": salary, "tax_percent": tax_percent}, namespaces=["Input Page"])

    if total:
        MultiPage.save({"total": total}, namespaces=["Net Salary"])


def compute_page(st, **state):
    st.title("Your Salary After Taxes")

    if "total" not in state:
        st.warning("Enter your data before computing. Go to the Input Page")
        return

    total = state["total"]

    st.metric("Total", round(total, 2))


app = MultiPage()
app.st = st

app.add_app("Input Page", input_page)
app.add_app("Net Salary", compute_page)

app.run()

Directory Structure

When dealing with multiple, complex pages, it is not convenient to have them all in a single .py file. This example shows how to lay out the directory structure to have an organize project.

.
└── root/
    ├── pages/
    │   ├── __init__.py
    │   ├── input_data.py
    │   └── result.py
    └── main.py/

input_data.py

from streamlit_multipage import MultiPage


def input_page(st, **state):
    st.title("Tax Deduction")

    salary_ = state["salary"] if "salary" in state else 0.0
    salary = st.number_input("Your salary (USD): ", value=salary_)

    tax_percent_ = state["tax_percent"] if "tax_percent" in state else 0.0
    tax_percent = st.number_input("Taxes (%): ", value=tax_percent_)

    total = salary * (1 - tax_percent)

    if tax_percent and salary:
        MultiPage.save({"salary": salary, "tax_percent": tax_percent}, namespaces=["Input Page"])

    if total:
        MultiPage.save({"total": total}, namespaces=["Net Salary"])

Result.py

def compute_page(st, **state):
    st.title("Your Salary After Taxes")

    if "total" not in state:
        st.warning("Enter your data before computing. Go to the Input Page")
        return

    total = state["total"]

    st.metric("Total", round(total, 2))

__init__.py

from .input_data import input_page
from .result import compute_page

pages = {
    "Input Page": input_page,
    "Net Salary": compute_page,
}

main.py

from pages import pages

import streamlit as st
from streamlit_multipage import MultiPage


app = MultiPage()
app.st = st

for app_name, app_function in pages.items():
    app.add_app(app_name, app_function)

app.run()

Landing Page

In is also possible to show a landing page that will be show only on start up and then redirect to the main app. The landing page is merely informative and has no access to the state.

import streamlit as st
from streamlit_multipage import MultiPage, save


def input_page(st, **state):
    """See Example on Multipage"""


def compute_page(st, **state):
    """See Example on Multipage"""


def landing_page(st):
    st.title("This is a Multi Page Application")
    st.write("Feel free to leave give a star in the Github Repo")


app = MultiPage()
app.st = st

app.add_app("Landing", landing_page, initial_page=True)
app.add_app("Input Page", input_page)
app.add_app("BMI Result", compute_page)

app.run()

Customization

There is additional functionality to customized the UI. In this example all the default text is replaced with custom messages.

import streamlit as st
from streamlit_multipage import MultiPage, save


def input_page(st, **state):
    """See Example on Multipage"""


def compute_page(st, **state):
    """See Example on Multipage"""


def landing_page(st):
    """See Example on Landing Page"""


def footer(st):
    st.write("Developed by [ELC](https://elc.github.io)")


def header(st):
    st.write("This app is free to use")


def sidebar(st):
    st.button("Donate (Dummy)")


app = MultiPage()
app.st = st

app.start_button = "Go to the main page"
app.navbar_name = "Other Pages:"
app.next_page_button = "Next Chapter"
app.previous_page_button = "Previous Chapter"
app.reset_button = "Delete Cache"
app.navbar_style = "SelectBox"

app.header = header
app.footer = footer
app.navbar_extra = sidebar

app.hide_menu = True
app.hide_navigation = True

app.add_app("Landing", landing_page, initial_page=True)
app.add_app("Input Page", input_page)
app.add_app("BMI Result", compute_page)

app.run()

Installation

No Install

This is a really simple script, if introducing new and small dependencies is not desired, simply copy and paste the content of the src folder into your project (one single file). Beware that this method does not include all the advantages of using a dependency such as updates, dependency tracking and so on.

Via Pip

Install by running

pip install streamlit-multipage

The only dependency is streamlit which should be already installed. It will be installed automatically if not present. Optionally, joblib can be installed if the pickle module cannot handle the object in the saved state.

Similar projects

Having multi page streamlit app is something many people try to achieve, therefore, many libraries were developed to achieved this goal. Some of them are listed below:

If this project does not fit your needs, please check these as well.

Maintainers

This project is maintained by Yan Almeida and Ezequiel Leonardo Castaño

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

streamlit-multipage-0.0.18.tar.gz (21.1 kB view details)

Uploaded Source

Built Distribution

streamlit_multipage-0.0.18-py3-none-any.whl (19.2 kB view details)

Uploaded Python 3

File details

Details for the file streamlit-multipage-0.0.18.tar.gz.

File metadata

  • Download URL: streamlit-multipage-0.0.18.tar.gz
  • Upload date:
  • Size: 21.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.63.0 importlib-metadata/4.11.2 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.10

File hashes

Hashes for streamlit-multipage-0.0.18.tar.gz
Algorithm Hash digest
SHA256 698bc4af147c9d76a17ba0df286547c8e167255df08eb50e353349b606e74a11
MD5 06d4b21b9c004fb193438882de691dcb
BLAKE2b-256 a5677fb1b44fb4db4d5589bb2570c90c6ade3d5136253ce65c9abd8aa534d7d4

See more details on using hashes here.

File details

Details for the file streamlit_multipage-0.0.18-py3-none-any.whl.

File metadata

  • Download URL: streamlit_multipage-0.0.18-py3-none-any.whl
  • Upload date:
  • Size: 19.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.63.0 importlib-metadata/4.11.2 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.10

File hashes

Hashes for streamlit_multipage-0.0.18-py3-none-any.whl
Algorithm Hash digest
SHA256 a9a4da06c29ef312878b7ea968cc4f130a0f37c2f738b259a52885bddf18b78c
MD5 c39aa9460454db931bf3ffd078baf8f6
BLAKE2b-256 30781439908daa1ea572a8b2b455d9d8ce95bd0f8390d0514224575212084c51

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page