streamlit: st.download_button() should not rerun the entire page

Hi folks,

Please, consider the MWE below:

import streamlit as st
import pandas as pd

with st.form(key='form1'): 
   user_input = st.text_input("Insert text")
   submit = st.form_submit_button("Submit")

if submit:    
  st.warning("This part should not be lost after clicking the download button!")  
  st.write(user_input) 
   
   # Save dataframe as a .csv file
   df = pd.DataFrame({"v1": [1,2,3]})    
   file_name = "df.csv"
   file_path = f"./{file_name}"
   #
   df.to_csv(file_path)   
   # Create Download Button
   file_bytes = open(file_path, 'rb')
   st.download_button(label='Click to download',
                       data=file_bytes, 
                       file_name=file_name,
                       key='download_df')
   file_bytes.close()

Problem

st.download_button() reruns the entire page, erasing everything that was opened after clicking “Submit”. This behavior can be problematic, specially for applications that use st.form() like this one.

Solution

Having an option in st.download_button() to not rerun anything would be really great.

Thank you

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 27
  • Comments: 36 (3 by maintainers)

Most upvoted comments

Thanks @vdonato !

Actually, I believe all suitable Streamlit components should have a rerun parameter with 3 options:

  • rerun the entire page (currently the default behavior)
  • rerun everything below the current component but nothing above
  • rerun nothing

@kajarenc , I also don’t know how difficult it would be to implement it but in my view it would put Streamlit in another level of capabilities and fulfill the requirements of more intermediate/advanced developers.

Please let me know what you guys think about this and if I should open a separate issue for that.

Streamlit is awesome and with just a few improvements I believe it will be unstoppable.

Actually, I believe all suitable Streamlit components should have a rerun parameter with 3 options:

  • rerun the entire page (currently the default behavior)
  • rerun everything below the current component but nothing above
  • rerun nothing

I truly believe without this Streamlit will repel a lot of users.

any update on this issue?

This custom download button downloads without rerunning the page, I’ve found it quite useful: https://gist.github.com/chad-m/6be98ed6cf1c4f17d09b7f6e5ca2978f

Love this idea. Can’t think of any reason a download button should rerun the page, but plenty of reasons it should not!

PS - Streamlit rocks. Total lifesaver.

Hey, We are currently facing the same issue, is there any chance for a workaround? We tried to fix with session state with no success.

Is there a reason why you cannot cache what is expensive to calculate, or store a value in sessions state?

import streamlit as st
import pandas as pd

with st.form(key='form1'): 
   user_input = st.text_input("Insert text")
   submit = st.form_submit_button("Submit")

if submit:
  st.session_state.submitted = True

if 'submitted' in st.session_state:
  st.warning("This part should not be lost after clicking the download button!")  
  st.write(user_input) 
  ...   

In fact I am using st_session_state to store dataframes, plots etc and check if they are set in order to skip calculations. But I think this is a workaround that adds too much workflow management in the software. I still think it is a better option to add run control to some streamlit widgets, as in the download button

Is there a reason why you cannot cache what is expensive to calculate, or store a value in sessions state?

import streamlit as st
import pandas as pd

with st.form(key='form1'): 
   user_input = st.text_input("Insert text")
   submit = st.form_submit_button("Submit")

if submit:
  st.session_state.submitted = True

if 'submitted' in st.session_state:
  st.warning("This part should not be lost after clicking the download button!")  
  st.write(user_input) 
  ...   

@karenarcoverde , hey, I have wrote an extension https://github.com/PaleNeutron/streamlit-ext .

Which provide a download button allow user download without rerun.

But note, this donwload button currently will embed downloaded file in page, so if you create a button which download a 10 Mb file, every time people view this page will load 10 Mb data!

@owos , Just pip install streamlit-ext.

Thanks @madshaven , it’s a good workaround indeed. But I still think it’s annoying that Streamlit makes every little user action rerun the entire page.

any updates on this? I have a page that performs a time consuming calculations and show plots with results and a download button to get a file with data. If I click to download the data the page needs to rerun again, taking a very long time.

I actually disagree. It seems like the idea of streamlit to rerun when something change. Clicking should make a change.