Dear all,
I am a total Dash newbie and have a question concerning uploading files, when the module upload.py is part of a multipage app. When I try to upload Excel or CSV Data, nothing happens (also no error messages, it looks like the file upload isnt happening at all. No data table is created).
I assume the error lies in the way my modules are connected / not properly connected, but I am fresh out of ideas on how to solve the issue.
Here the code:
(1) module app.py
import dash
import dash_bootstrap_components as dbc
from dash import html, dcc
import plotly.express as px
from dash.dependencies import Input, Output
import pandas as pd
# Connect to main app.py file
#from app import app
#for deployment
#from app import server
# Connect to your app pages
from pages import analysis, optimisation, upload
app = dash.Dash(__name__,
suppress_callback_exceptions=True,
external_stylesheets=[dbc.themes.BOOTSTRAP]
)
server = app.server
# styling the sidebar
SIDEBAR_STYLE = {
"position": "fixed",
"top": 0,
"left": 0,
"bottom": 0,
"width": "20rem",
"padding": "2rem 1rem",
"background-color": "#FF0000",
"font-family": "Arial"
}
# padding for the page content
CONTENT_STYLE = {
"margin-left": "20rem",
"margin-right": "2rem",
"padding": "1rem 1rem",
}
NAV_TEXT_STYLE = {
"color": "#FFFFFF",
}
NAV_LINK_STYLE = {
"color": "#FFFFFF",
}
#company logo image path
image_path = 'assets/sid_str.png'
#sidebar
sidebar = html.Div(
[
html.H2("GDX", className="display-4", style=NAV_TEXT_STYLE),
html.P(
"CO2 und Kostenbewertung für Gebäude", className="lead", style=NAV_TEXT_STYLE
),
html.Hr(),
dbc.Nav(
[
dbc.NavLink("Upload", href="/pages/upload", active="exact", style=NAV_LINK_STYLE),
dbc.NavLink("Analysis", href="/pages/analysis", active="exact", style=NAV_LINK_STYLE),
dbc.NavLink("Optimisation", href="/pages/optimisation", active="exact", style=NAV_LINK_STYLE),
],
vertical=True,
pills=True,
),
html.Img(src=image_path)
],
style=SIDEBAR_STYLE,
)
#define app layout
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
sidebar,
html.Div(id='page-content', children=[], style=CONTENT_STYLE) #content
])
#callback component property pathname, returns are inserted into children=[]
@app.callback(Output('page-content', 'children'),
[Input('url', 'pathname')])
def display_page(pathname):
if pathname == '/pages/upload':
return upload.layout
if pathname == '/pages/analysis':
#return analysis.layout
return "404 Page Error! Please choose a link"
else:
return "404 Page Error! Please choose a link"
if __name__ == '__main__':
app.run_server(debug=True)
(2) module upload.py
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
from dash import html, dcc, dash_table
import plotly.express as px
import pandas as pd
from app import app
#dash.register_page(__name__)
layout = html.Div(
[
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files', style={"color":"blue", "text-decoration": "underline blue"})
]),
style={
'width': '50%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin-top': '10px',
'margin-bottom': '10px',
'margin-left': '10px',
'margin-right': '30px'
},
# Allow multiple files to be uploaded
multiple=False
),
html.Div(id='output-div'),
html.Div(id='output-datatable'),
])
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
print("Its a CSV!")
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xlsx' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
html.P("Inset X axis data"),
dcc.Dropdown(id='xaxis-data',
options=[{'label':x, 'value':x} for x in df.columns]),
html.P("Inset Y axis data"),
dcc.Dropdown(id='yaxis-data',
options=[{'label':x, 'value':x} for x in df.columns]),
html.Button(id="submit-button", children="Create Graph"),
html.Hr(),
dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'name': i, 'id': i} for i in df.columns],
page_size=15
),
dcc.Store(id='stored-data', data=df.to_dict('records')),
html.Hr(), # horizontal line
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
@app.callback(Output('output-datatable', 'children'),
Input('upload-data', 'contents'),
State('upload-data', 'filename'),
State('upload-data', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
@app.callback(Output('output-div', 'children'),
Input('submit-button','n_clicks'),
State('stored-data','data'),
State('xaxis-data','value'),
State('yaxis-data', 'value'))
def make_graphs(n, data, x_data, y_data):
if n is None:
return dash.no_update
else:
bar_fig = px.bar(data, x=x_data, y=y_data)
# print(data)
return dcc.Graph(figure=bar_fig)
Any hints and tips are greatly appreciated!
Thanks!