[streamlit] st.Page 및 st.navigation으로 다중 페이지 앱(multi page apps) 정의하기

[출처] https://docs.streamlit.io/develop/concepts/multipage-apps/page-and-navigation

 

Streamlit Docs

Join the community Streamlit is more than just a way to make data apps, it's also a community of creators that share their apps and ideas and help each other make their work better. Please come join us on the community forum. We love to hear your questions

docs.streamlit.io


st.Page 및 st.navigation은 다중 페이지 앱을 정의하는 데 선호되는 명령어입니다. 이 명령을 사용하면 프로젝트 파일을 유연하게 구성하고 탐색 메뉴를 사용자 지정할 수 있습니다. st.Page로 StreamlitPage 객체를 초기화한 다음, 해당 StreamlitPage 객체를 엔트리포인트 파일(즉, streamlit 실행에 전달하는 파일)의 st.navigation에 전달하기만 하면 됩니다.

이 페이지에서는 개요에 제시된 페이지 용어를 이해했다고 가정합니다.

1. App structure

st.navigation을 사용할 때 엔트리포인트 파일은 페이지 라우터처럼 작동합니다. 각 페이지는 엔트리포인트 파일에서 실행되는 스크립트입니다. Python 파일이나 함수에서 페이지를 정의할 수 있습니다. 엔트리포인트 파일에 요소나 위젯을 포함하면 페이지 간에 공통 요소가 됩니다. 이 경우 엔트리포인트 파일을 각 페이지를 둘러싼 액자처럼 생각할 수 있습니다.

앱 실행당 한 번만 st.navigation을 호출할 수 있으며 엔트리포인트 파일에서 호출해야 합니다. 사용자가 탐색에서 페이지를 선택하거나 st.switch_page와 같은 명령을 통해 라우팅되는 경우 st.navigation은 선택한 페이지를 반환합니다. .run() 메서드를 사용하여 해당 페이지를 수동으로 실행해야 합니다. 다음 예제는 각 페이지가 Python 파일로 정의된 두 페이지 앱입니다.

Directory structure:

your-repository/
├── page_1.py
├── page_2.py
└── streamlit_app.py

streamlit_app.py:

import streamlit as st

pg = st.navigation([st.Page("page_1.py"), st.Page("page_2.py")])
pg.run()

 

2. Defining pages

st.Page를 사용하면 페이지를 정의할 수 있습니다. 첫 번째이자 유일한 필수 인수는 페이지 소스를 정의하며, 파이썬 파일이나 함수일 수 있습니다. Python 파일을 사용하는 경우 페이지는 하위 디렉터리(또는 상위 디렉터리)에 있을 수 있습니다. 페이지 파일의 경로는 항상 엔트리포인트 파일에 상대적이어야 합니다. 페이지 객체를 생성한 후에는 이를 st.navigation에 전달하여 앱에 페이지로 등록합니다.

페이지 제목이나 URL 경로명을 정의하지 않으면 스트림릿은 다중 페이지 앱 개요에 설명된 대로 파일 또는 함수 이름에서 이를 유추합니다. 그러나 st.Page를 사용하면 수동으로 구성할 수 있습니다. st.Page 내에서 Streamlit은 title을 사용하여 페이지 레이블과 제목을 설정합니다. 또한 스트림릿은 아이콘을 사용하여 페이지 아이콘과 파비콘을 설정합니다. 다른 페이지 제목과 레이블 또는 다른 페이지 아이콘과 파비콘을 사용하려면 st.set_page_config를 사용하여 페이지 제목 및/또는 파비콘을 변경할 수 있습니다. 엔트리포인트 파일이나 페이지 소스에서 st.navigation 뒤에 st.set_page_config를 호출하면 됩니다.

다음 예는 st.set_page_config를 사용하여 페이지 제목과 파비콘을 페이지 전체에 일관되게 설정하는 방법입니다. 탐색 메뉴에는 각 페이지마다 고유한 레이블과 아이콘이 표시되지만 브라우저 탭에는 모든 페이지에 일관된 제목과 파비콘이 표시됩니다.

Directory structure:

your-repository/
├── create.py
├── delete.py
└── streamlit_app.py

streamlit_app.py:

import streamlit as st

create_page = st.Page("create.py", title="Create entry", icon=":material/add_circle:")
delete_page = st.Page("delete.py", title="Delete entry", icon=":material/delete:")

pg = st.navigation([create_page, delete_page])
st.set_page_config(page_title="Data manager", page_icon=":material/edit:")
pg.run()

3. Customizing navigation

페이지를 섹션으로 그룹화하려는 경우 st.navigation을 사용하면 탐색 내에 헤더를 삽입할 수 있습니다. 또는 기본 탐색 위젯을 비활성화하고 st.page_link를 사용하여 사용자 정의 탐색 메뉴를 만들 수 있습니다.

또한 st.navigation에 전달할 페이지를 동적으로 변경할 수 있습니다. 그러나 st.navigation에서 반환되는 페이지만 .run() 메서드를 허용합니다. 사용자가 경로명이 포함된 URL을 입력했는데 해당 경로명이 (처음 실행 시) st.navigation의 페이지에 연결되지 않은 경우 Streamlit은 "페이지를 찾을 수 없음" 오류를 발생시키고 사용자를 기본 페이지로 리디렉션합니다.

4. Adding section headers

탐색 메뉴에서 액세스 가능한 유효한 페이지를 숨기고 싶지 않은 경우 탐색 메뉴를 사용자 지정하는 가장 간단한 방법은 st.navigation 내에서 페이지를 구성하는 것입니다. 페이지를 정렬하거나 그룹화할 수 있을 뿐만 아니라 사용자가 액세스하지 않기를 원하는 페이지를 제거할 수도 있습니다. 이는 사용자 권한을 처리하는 편리한 방법입니다.

다음 예에서는 두 가지 메뉴 상태를 만듭니다. 사용자가 새 세션을 시작하면 로그인되지 않습니다. 이 경우 사용 가능한 유일한 페이지는 로그인 페이지입니다. 사용자가 URL을 통해 다른 페이지에 액세스하려고 하면 새 세션이 생성되고 Streamlit은 해당 페이지를 인식하지 못합니다. 사용자는 로그인 페이지로 리디렉션됩니다. 그러나 사용자가 로그인하면 세 개의 섹션으로 구성된 탐색 메뉴가 표시되고 앱의 기본 페이지(즉, 홈페이지)인 대시보드로 이동합니다.

Directory structure:

your-repository/
├── reports
│   ├── alerts.py
│   ├── bugs.py
│   └── dashboard.py
├── tools
│   ├── history.py
│   └── search.py
└── streamlit_app.py

streamlit_app.py:

import streamlit as st

if "logged_in" not in st.session_state:
    st.session_state.logged_in = False

def login():
    if st.button("Log in"):
        st.session_state.logged_in = True
        st.rerun()

def logout():
    if st.button("Log out"):
        st.session_state.logged_in = False
        st.rerun()

login_page = st.Page(login, title="Log in", icon=":material/login:")
logout_page = st.Page(logout, title="Log out", icon=":material/logout:")

dashboard = st.Page(
    "reports/dashboard.py", title="Dashboard", icon=":material/dashboard:", default=True
)
bugs = st.Page("reports/bugs.py", title="Bug reports", icon=":material/bug_report:")
alerts = st.Page(
    "reports/alerts.py", title="System alerts", icon=":material/notification_important:"
)

search = st.Page("tools/search.py", title="Search", icon=":material/search:")
history = st.Page("tools/history.py", title="History", icon=":material/history:")

if st.session_state.logged_in:
    pg = st.navigation(
        {
            "Account": [logout_page],
            "Reports": [dashboard, bugs, alerts],
            "Tools": [search, history],
        }
    )
else:
    pg = st.navigation([login_page])

pg.run()

5. Dynamically changing the available pages

st.navigation에서 페이지 목록을 업데이트하여 사용자가 사용할 수 있는 페이지를 변경할 수 있습니다. 이는 특정 페이지에 대한 역할 기반 또는 사용자 기반 액세스를 처리하는 편리한 방법입니다. 자세한 내용은 동적 탐색 메뉴 만들기 튜토리얼을 참조하세요.

6. Building a custom navigation menu

내비게이션 메뉴를 더 세밀하게 제어하고 싶다면 기본 내비게이션을 숨기고 나만의 내비게이션을 만들 수 있습니다. st.navigation 명령에 position="hidden"을 포함하면 기본 탐색을 숨길 수 있습니다. 탐색 메뉴에 페이지를 표시하지 않고 사용자가 페이지를 사용할 수 있게 하려면 이 방법을 사용해야 합니다. 페이지가 st.navigation에 포함되지 않은 경우 사용자를 페이지로 라우팅할 수 없습니다. 이는 URL을 통한 탐색뿐만 아니라 st.switch_page 및 st.page_link와 같은 명령에도 적용됩니다.