I figured it out
Note that the directory stage is where my temporary download files are stored
First this is what my directory tree looks like:
root
|
|---apps
| └── main.py
|---assets
|---layouts
| |--layout.py
| └── error.py
|---stage
|---app.py
|---functions.py
└── index.py
This is what my index.py looks like
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from app import app
from apps import main
app.layout = html.Div(
[dcc.Location(id="url", refresh=False), html.Div(id="page-content")]
)
@app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def display_page(pathname):
if pathname == "/main":
return main.layout
else:
return main.error_page
if __name__ == "__main__":
app.run_server(debug=True, host="llp-lnx-dt-10200", port=15021)
in functions.py I will dynamically produce a dash-table + the html.A(... with the link to download, the function is
def display_final_results(table):
import dash_html_components as html
import dash_core_components as dcc
import dash_table
import pandas as pd
return html.Div(
[
html.H5("""File processed and stuff worked"""),
dash_table.DataTable(
id="result_table",
data=table.iloc[:20, :].to_dict("records"),
columns=[{"name": i, "id": i} for i in list(table)],
),
html.Hr(),
dcc.Store(id="result_vault", data=table.to_dict()),
html.A(id="download_link", children=html.Button(children="Download")),
]
)
in main.py I call on the function def_final_results(table) passing in the table that I want to display in the dash-table and also the link for download.
Here's what the callback in main.py looks like followed by the app.server.route()
@app.callback(
Output("download_link", "href"),
[Input("result_vault","data"),
Input("h5_filename", "children")]
)
def return_download_link(data, upload_filename):
shutil.rmtree("stage")
os.mkdir("stage")
target = pd.DataFrame(data)
download_filename = upload_filename.split(":")[1].strip() + f"""_{filestamp()}.xlsx"""
uri = f"""stage/{download_filename}"""
target.to_excel(
uri, engine="xlsxwriter", index=False, header=True, sheet_name="results"
)
return uri
@app.server.route("/stage/<path:path>")
def serve_static(path):
root_dir = os.getcwd()
return flask.send_from_directory(os.path.join(root_dir, "stage"), filename=path)
in main.py the table target is saved into the directory /stage and the uri object which is the path to the file /stage/filename+filestamp is sent to object with id download_link as the href attribute, this is the html.A(... in the file functions.py. I returned the href since the download attribute did not work for me.
The big mistake that I made was that my index.py dcc.Location url used to be:
if pathname == "apps/main":
return main.layout
So every time the routing would go to https://llp-lnx-dt-10200:15021/apps/stage/filename
rather than https://llp-lnx-dt-10200:15021/stage/filename.
By removing the apps from the url the problem was promptly solves.