【问题标题】:Is there a way to add the "select all" option in the multiselect widget of python's streamlit package?有没有办法在 python 的 streamlit 包的多选小部件中添加“全选”选项?
【发布时间】:2020-11-13 12:17:47
【问题描述】:

我正在开发一个 streamlit 应用程序,其中包含一个带有 10 个选项的多选小部件。是否有替代方法可以添加一个选择所有选项的按钮以避免一一选择?

我尝试向多选添加上一个按钮,但使用另一个小部件会重置选择。这是一个示例代码:

import streamlit as st

if st.sidebar.button('Add all years'):
    year_filter = st.sidebar.multiselect('Select a year',[2000,2001,2002,2003,2004], default=[2000,2001,2002,2003,2004])
else:
    year_filter = st.sidebar.multiselect('Select a year',[2000,2001,2002,2003,2004], default=[2000])

type_filter = st.sidebar.multiselect('Choose a type',['Control','Experimental'], default=['Experimental'])

st.write(year_filter, type_filter)

【问题讨论】:

    标签: python multi-select streamlit


    【解决方案1】:

    有一种方法可以使用state

    import streamlit as st
    from streamlit.ReportThread import get_report_ctx
    from streamlit.hashing import _CodeHasher
    from streamlit.server.Server import Server
    
    
    class _SessionState:
        def __init__(self, session, hash_funcs):
            """Initialize SessionState instance."""
            self.__dict__["_state"] = {
                "data": {},
                "hash": None,
                "hasher": _CodeHasher(hash_funcs),
                "is_rerun": False,
                "session": session,
            }
    
        def __call__(self, **kwargs):
            """Initialize state data once."""
            for item, value in kwargs.items():
                if item not in self._state["data"]:
                    self._state["data"][item] = value
    
        def __getitem__(self, item):
            """Return a saved state value, None if item is undefined."""
            return self._state["data"].get(item, None)
            
        def __getattr__(self, item):
            """Return a saved state value, None if item is undefined."""
            return self._state["data"].get(item, None)
    
        def __setitem__(self, item, value):
            """Set state value."""
            self._state["data"][item] = value
    
        def __setattr__(self, item, value):
            """Set state value."""
            self._state["data"][item] = value
        
        def clear(self):
            """Clear session state and request a rerun."""
            self._state["data"].clear()
            self._state["session"].request_rerun()
        
        def sync(self):
            """Rerun the app with all state values up to date from the beginning to fix rollbacks."""
    
            # Ensure to rerun only once to avoid infinite loops
            # caused by a constantly changing state value at each run.
            #
            # Example: state.value += 1
            if self._state["is_rerun"]:
                self._state["is_rerun"] = False
            
            elif self._state["hash"] is not None:
                if self._state["hash"] != self._state["hasher"].to_bytes(self._state["data"], None):
                    self._state["is_rerun"] = True
                    self._state["session"].request_rerun()
    
            self._state["hash"] = self._state["hasher"].to_bytes(self._state["data"], None)
    
    
    def _get_session():
        session_id = get_report_ctx().session_id
        session_info = Server.get_current()._get_session_info(session_id)
    
        if session_info is None:
            raise RuntimeError("Couldn't get your Streamlit Session object.")
        
        return session_info.session
    
    
    def _get_state(hash_funcs=None):
        session = _get_session()
    
        if not hasattr(session, "_custom_session_state"):
            session._custom_session_state = _SessionState(session, hash_funcs)
    
        return session._custom_session_state
    
    
    def main():
        state = _get_state()
    
        if state.previous_years_selected is None:
            state.previous_years_selected = [2000]
        
        if st.sidebar.button('Add all years'):
            year_filter = st.sidebar.multiselect('Select a year', [2000,2001,2002,2003,2004], default=[2000,2001,2002,2003,2004])
        else:
            year_filter = st.sidebar.multiselect('Select a year', [2000,2001,2002,2003,2004], default=state.previous_years_selected)
    
        # The next default (in case no one clicks on "Add all years")
        # will be the current years selected
        state.previous_years_selected = year_filter
    
        state.sync()
    
    
    if __name__ == "__main__":
        main()
    

    _StateSession 对象在 Streamlit 的重新加载过程中保留数据,这意味着如果您与小部件交互,页面会重新加载,但 state 保留信息。
    在这里,我们保留上次与“年份选择器”交互期间选择的年份信息,并将其作为下次重新加载的默认值 (default=state.previous_years_selected)。

    您可以将任何您想要的数据添加到state 对象。在修改它之前确保它确实存在:

    if state.previous_years_selected is None:
        state.previous_years_selected = [2000]
    

    【讨论】:

    • 非常有帮助,谢谢!我只需要调整导入以使其在 streamlit 0.72 下工作:from streamlit.server.server import Serverfrom streamlit.report_thread import get_report_ctx
    猜你喜欢
    • 2016-03-31
    • 1970-01-01
    • 2022-06-16
    • 2020-02-26
    • 1970-01-01
    • 2022-08-18
    • 2013-06-15
    • 2022-10-08
    • 1970-01-01
    相关资源
    最近更新 更多