Sorry for not answering, yesterday I decided to leave this aside for a bit while I went on with another project.
The refresh didn’t work either, so I decidec to do a twist and try with the clientside callback. I added in the layout a hidden P component (Children = “None”) that would hold the URL that the clientside callback will use. Then, I modify my previous callback
@app.callback(Output("data_dowload_link", "children"),
[Input("download_data_button", "n_clicks"),
Input("user", "value")])
def download_data_to_csv(n_clicks, user_current):
if "download_prod_data_button.n_clicks" in ctx.triggered_prop_ids:
#This function returns a set of selection of the current user
data = get_selections(user_current)
#Function that returns a filtered pandas Data Frame
df = apply_filters(production_df, data)
#Prepare the credentials to conect towards the Cloud Storage
credentials, project_id = auth.default()
credentials.refresh(auth.transport.requests.Request())
service_account_email = credentials.service_account_email
#Connect to the Cloud Storage Client
storage_client = storage.Client()
bucket_storage = storage_client.bucket("my_bucket")
user_blob_path = f"{user_current}/my_dataframe.csv"
df_blob = bucket_storage.blob(user_blob_path)
#Write the DF into Cloud Storage to create the signed URL
df_blob.upload_from_string(df.to_csv(), 'text/csv', timeout=360)
url = df_blob.generate_signed_url(
version="v4",
expiration=datetime.timedelta(minutes=1),
method="GET",
service_account_email=service_account_email,
access_token=credentials.token
)
# all done
return url
And then added the next code, following the information given in Dash documentation and some other post:
app.clientside_callback(
"""
function open_cloud_storage_download_url(download_url) {
if (download_url != "None") {
window.open(download_url, "_blank");
return "None"; //Erase the url after use it
}
}
"""
Output("data_download_link", "children"),
Input("data_download_link", "children")
)
This “shooooouuuuuuld” work, but it doesn’t. To be more precise, when I open the app, once again it is blank. I might have clue of what is going on.
To go back on how the app is build (Once again, I’m not a Dash expert and the person who build the app neither):
The main layout of the app are two div components and a dcc.Location component inside a main div component. The first div is a menu bar that allows to navigate around the page, and it has various dbc.NavLink components inside a dbc.Nav. Meanwhile, the second div is where the different pages of the app are displayed. When opening the app, in the second div appears the initial page, the “Home page” of the app, where the download button is located. When the user clicks on any of the dbc.NavLink of the first div, a callback is triggered that gets the pathname of the dcc.Location and changes the second div display depending on the value of the pathname.
On code:
app.layout = htmlDiv([dcc.Location(id="app_url"), menu_bar, main_content,
html.P("None", id="data_download_link", style= {"display": "none"})])
#This would be another .py file that has the callback for the first div
@app.callback(Output("page-content", "children"),
[Input("app_url", "pathname")])
def show_page_content(pathname):
#Each value of the returns are a layout imported from others .py
if pathname == "/":
return main_page
elif pathname == "/page-1":
return first_page
elif pathname == "/page-2":
return second_page
#This would be another .py file that has the layout of the two divs
MENU_STYLE = {
"position": "fixed",
"top": 0,
"left": 0,
"bottom": 0,
"width": "16rem",
"padding": "2rem 2rem",
"background-color": "#f8f9fa",
}
menu_bar = html.Div(
[
dbc.Nav(
[
dbc.NavLink("Main Page",
id="home-navlink",
disabled=False,
href="/",
active="exact"),
dbc.NavLink("Page 1",
id="first-navlink",
disabled=False,
href="/page-1",
active="exact"),
dbc.NavLink("Page 2",
id="second-navlink",
href="/page-2",
disabled=False,
active="exact")
],
vertical=True,
pills=True,
),
],
style=SIDEBAR_STYLE,
)
CONTENT_STYLE = {
"top": 0,
"left": 0,
"bottom": 0,
"padding": "2rem 2rem",
"margin-left": "15rem",
"margin-right": "0rem",
}
main_content = html.Div(id="page-content", style=CONTENT_STYLE)
I might think that, somehow the java script code that calls the windows.open interferes with the dcc.Location the dbc.NavLink somehow and the main_content component, given that when I open the app, the menu bar appears, but the main content does not. And if I click any of the NavLink, the main_content doesnt change. But I take out the clientside_callback, everything works fine (Except that I don’t get to call the URL)
Any leads from there?