Hi, I am using dash to build a multipage app that basically does a correlation analysis with some variables pulled from a database using an API against user uploaded data.
I am trying to use the upload module and have a hidden layer in the app to have the user-uploaded dataset available across pages. But when I try to upload the dataset, it gives me JSON related errors.
The goal of this topic is to understand how to store a user-uploaded data for the session and have it available across pages. I’m also trying to display the data in a table after upload. Then, the “Analyze” button will serve as a callback to call a python script that would pull the API and perform the correlation analysis with the pulled data and user-uploaded data and store the result and display in graph/table format.
when I try to upload a simple csv file, it gives me an error. Code and error below:
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import base64
import io
import os
import dash
import pandas as pd
from datetime import datetime as dt
import dash_table_experiments as dte
import plotly
import json
import numpy as np
import flaskprint(dcc.version) # 0.6.0 or above is required
app = dash.Dash()
app.config.suppress_callback_exceptions = Trueapp.layout = html.Div([
dcc.Location(id=‘url’, refresh=False),
# This is the ‘hidden div’ however its really a container for sub-divs, some hidden, some not
html.Div(id=‘output-data-upload’),
html.Br(),
html.Div(id=‘page-content’),])
STARTING PAGE
home_page = html.Div([
dcc.Markdown(‘’’
rules and guidelines for the tool
‘’‘),
html.Br(),
dcc.Link(‘Upload My Data’, href=’/page-1’),
html.Br(),
dcc.Link(‘View Analysis’, href=‘/page-2’),
])#UPLOAD DATA PAGE
upload_page = html.Div([
html.H3(‘Select Data for Analysis’),
#UPLOAD DATA
dcc.Upload(
id=‘upload-data’,
children=html.Div([
'Drag and Drop or ',
html.A(‘Select Files’)
]),
style={
‘width’: ‘100%’,
‘height’: ‘60px’,
‘lineHeight’: ‘60px’,
‘borderWidth’: ‘1px’,
‘borderStyle’: ‘dashed’,
‘borderRadius’: ‘5px’,
‘textAlign’: ‘center’,
‘margin’: ‘10px’
},
),
html.Div(id = ‘Target-File’, style={‘display’: ‘none’}),
html.Div(id=‘output-data-upload’),SHOW THE UPLOADED DATA IN TABLE
how??
#DEFINE MIN DATE
html.Hr(), #horizontal line
html.H3(‘Select Minimum Date’),
html.Div([
dcc.DatePickerSingle(
id=‘min-date’,
min_date_allowed=dt(2010, 1, 1),
max_date_allowed=dt.now(),
initial_visible_month=dt.now(),
date=dt.now()
),
html.Div(id=‘min-date-value’)
]),
html.Br(),#DEFINE MAX DATE
html.H3(‘Select Maximum Date’),
html.Div([
dcc.DatePickerSingle(
id=‘max-date’,
min_date_allowed=dt(2010, 1, 1),
max_date_allowed=dt.now(),
initial_visible_month=dt.now(),
date=dt.now()
),
html.Div(id=‘max-date-value’)
]),#ANALYZE BUTTON
html.Hr(), #horizontal line
html.Div([
html.Button(id=‘analyze-button’, n_clicks=0, children=‘Analyze Data’),
html.Div(id=‘output-state’)
]),
html.Br(),
dcc.Link(‘View Analysis’, href=‘/page-2’),
html.Br(),
dcc.Link(‘Go to Home’, href=‘/’)
])#WHERE TO VIEW THE CORRELATION RESULTS
analysis_page = html.Div([
html.Div(id=‘output-data-upload’),
html.Div(id=‘analysis-page-content’),
html.Br(),
dcc.Link(‘Back to upload page’, href=‘/page-1’),
html.Br(),
dcc.Link(‘Go to Home’, href=‘/’)
])#FUNCTIONS
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(‘,’)decoded = base64.b64decode(content_string) try: if 'csv' in filename: # Assume that the user uploaded a CSV file target_df = pd.read_csv( io.StringIO(decoded.decode('utf-8'))) elif 'xls' in filename: # Assume that the user uploaded an excel file target_df = pd.read_excel(io.BytesIO(decoded)) except Exception as e: print(e) return html.Div([ 'There was an error processing this file.' ]) return filename, target_df
#DATA UPLOAD
@app.callback(Output(‘output-data-upload’, ‘children’),
[Input(‘upload-data’, ‘contents’),
Input(‘upload-data’, ‘filename’),
Input(‘upload-data’, ‘last_modified’)])
def update_output(contents, filename, date):
if contents is not None:
filename, target_df = parse_contents(contents, filename, date)
target_json = target_df.to_json(orient = “split”)
# This is the key to the hidden div formatting
return html.Div([
html.Div(['Uploaded file to analyze: ’ + filename]),
html.Div([target_json], id=‘Target-File’, style={‘display’: ‘none’})
], style={‘padding-top’: ‘20px’,‘align’: “center”})@app.callback(Output(‘output-state’, ‘children’),
[Input(‘analyze-button’, ‘n_clicks’)],
[State(‘Target-File’, ‘children’),
State(‘max-date-value’, ‘date’),
State(‘min-date-value’, ‘date’)])
def analysis_function(n_clicks,tankStats):
if n_clicks is not None:
# ALL THE API & ANALYSIS SCRIPTS
return ‘Analysis was successful!’#MIN DATE SETTING
@app.callback(
dash.dependencies.Output(‘min-date-value’, ‘children’),
[dash.dependencies.Input(‘min-date’, ‘date’)])
def update_mindate(date):
string_prefix = ‘Minimum date: ’
if date is not None:
date = dt.strptime(date, ‘%Y-%m-%d’)
date_string = date.strftime(’%B %d, %Y’)
return string_prefix + date_string#MAX DATE SETTING
@app.callback(
dash.dependencies.Output(‘max-date-value’, ‘children’),
[dash.dependencies.Input(‘max-date’, ‘date’)])
def update_maxdate(date):
string_prefix = ‘Maximum date: ’
if date is not None:
date = dt.strptime(date, ‘%Y-%m-%d’)
date_string = date.strftime(’%B %d, %Y’)
return string_prefix + date_stringUpdate the index
@app.callback(Output(‘page-content’, ‘children’), [Input(‘url’, ‘pathname’)])
def display_page(pathname):
if pathname == ‘/page-1’:
return upload_page
elif pathname == ‘/page-2’:
return analysis_page
elif pathname == ‘/’:
return home_page
else:
return “This page is invalid”app.css.append_css({‘external_url’:“https://codepen.io/chriddyp/pen/bWLwgP.css”})
if name == ‘main’:
app.run_server(debug=True)
Thanks for the help!