본문 바로가기

[5] streamlit form으로 데이터 추가하기

들어가며

🏫 전체 강의 영상

📕 포켓몬 도감 실습 프로젝트

 ▶️  강의 영상

 

이번 챕터에서는 streamlit form을 이용해서 유저의 입력을 받아서 포켓몬을 추가하는 기능을 구현해보겠습니다.

streamlit form

streamlit form은 유저의 입력을 받는 폼을 구성할 수 있는 기능입니다. 공식 문서에 코드 사용법과 예시 화면이 나와있습니다.

streamlit form 문서: https://docs.streamlit.io/library/api-reference/control-flow/st.form

텍스트 입력, 숫자 입력, 슬라이드 바, 체크 박스 등등 다양한 데이터를 입력하는 위젯을 제공하고 있으며, with문으로 사용할 수 있습니다. streamlit form은 반드시 Submit 버튼을 포함해야합니다. Submit 버튼 아래에 조건문을 작성해서 버튼이 눌렸을 때, 현재 입력된 데이터를 처리할 수 있습니다.

포켓몬 등록 form 구성

포켓몬을 등록하기 위해선 포켓몬의 이름, 속성, 이미지 URL이 필요합니다. 이 중에서 이름은 텍스트, 속성은 최대 element 개수가 2개인 배열, 이미지는 텍스트입니다. 이를 각각 st.text_input과 st.multiselect를 이용해서 폼을 구현하겠습니다.

 

form UI 코드는 포켓못들을 그려주는 코드 위쪽에 작성해줍니다. multiselect의 경우 option은 type_emoji_dict의 키들, 최대 선택 개수는 2로 설정해줍니다.

with st.form(key="form"):
    name = st.text_input(label="포켓몬 이름")
    types = st.multiselect(
        label="포켓몬 속성",
        options=list(type_emoji_dict.keys()),
        max_selections=2,
    )
    image_url = st.text_input(label="포켓몬 이미지 URL")
    submit = st.form_submit_button(label="Submit")
    if submit:
        print("click submit")

그런데 포켓몬 이름과 속성은 큰 공간을 차지하지 않아도 괜찮겠죠? form 안에 columns를 적용해서 st.text_input 위젯과 st.multiselect 위젯을 한줄에 배치해보겠습니다.

예외처리 로직 작성

포켓몬을 추가할 때 포켓몬의 이름과 속성은 반드시 필요한 정보입니다. (이미지 URL의 경우 누락되었을 때 기본 이미지로 설정하는 로직을 추가할 예정입니다.) 이를 누락했을 경우, 유저에게 입력하라고 메세지를 보여주는 것이 좋겠죠? Submit 버튼을 눌렀을 때, 조건문에서 이를 구현해보겠습니다.

with st.form(key="form"):
    col1, col2 = st.columns(2)
    with col1:
        name = st.text_input(label="포켓몬 이름")
    with col2:
        types = st.multiselect(
            label="포켓몬 속성",
            options=list(type_emoji_dict.keys()),
            max_selections=2,
        )
    image_url = st.text_input(label="포켓몬 이미지 URL")
    submit = st.form_submit_button(label="Submit")
    if submit:
        if not name:
            st.error("포켓몬의 이름을 입력해주세요.")
        elif len(types) == 0:
            st.error("포켓몬의 속성을 적어도 한개 선택해주세요.")
        else:
            st.success("포켓몬을 추가할 수 있습니다.")

포켓몬 추가 로직 작성

마지막으로 필요한 정보가 모두 입력되었을 때, pokemons 배열에 새로운 포켓몬을 추가해줍니다. 이 때, 이미지 URL이 누락되어 있다면 기본 이미지로 설정해줍니다. 추가된 포켓몬은 화면에 표시됩니다.

with st.form(key="form"):
    col1, col2 = st.columns(2)
    with col1:
        name = st.text_input(label="포켓몬 이름")
    with col2:
        types = st.multiselect(
            label="포켓몬 속성",
            options=list(type_emoji_dict.keys()),
            max_selections=2,
        )
    image_url = st.text_input(label="포켓몬 이미지 URL")
    submit = st.form_submit_button(label="Submit")
    if submit:
        if not name:
            st.error("포켓몬의 이름을 입력해주세요.")
        elif len(types) == 0:
            st.error("포켓몬의 속성을 적어도 한개 선택해주세요.")
        else:
            st.success("포켓몬을 추가할 수 있습니다.")
            pokemons.append({
                "name": name,
                "types": types,
                "image_url": image_url if image_url else "./images/default.png"
            })

포켓몬이 추가되지 않는 현상

form을 이용해서 데이터를 입력받고 이를 pokemons 배열에 추가하여 화면에 그려보았습니다. 그런데 포켓몬을 더 추가해보면 8번째, 9번째에 추가되는 것이 아니라 7번째 위치에 계속해서 추가가 됩니다.

이는 streamlit form이 동작하는 방식 때문에 발생하는 현상으로, session state를 사용해서 해결할 수 있습니다. 이는 다음 챕터에서 이어서 다루겠습니다.

정리

이번 챕터에서는 form을 이용해서 유저의 입력을 받고, 데이터를 추가하는 기능을 구현해보겠습니다. 다음 챕터에서는 session state를 이용해서 데이터를 관리하는 방법을 배워보겠습니다.