dash dcc.Uploader not working in multipage app - plotly-dash

0
I have a multi-page dash app for generating custom dashboards based on user submission. I'm trying to create a secondary page for uploading files. The problem is that the dcc.Upload or the callback function does not produce the expected behavior, that is: a html.Div that shows the uploaded data.
This is my secondary page, organized in tabs:
import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
import dash_mantine_components as dmc
from dash import dash_table
from dash.exceptions import PreventUpdate
import os
import unicodedata
import requests
from bs4 import BeautifulSoup
from urllib.request import urlopen
from urllib.parse import quote as urlquote
import sqlite3
from dash_iconify import DashIconify
from dash.dependencies import Input, Output, State
import pandas as pd
from app import app
def layout():
return [
dmc.Tabs(
[
dmc.TabsList(
[
dmc.Tab("Import", value="import"),
dmc.Tab("Connect BD", value="connectbd"),
dmc.Tab("Explore", value="explore"),
]
),
dmc.TabsPanel(
html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '260px',
'lineHeight': '60px',
'borderWidth': '1px',
#'borderStyle': 'dashed',
'background' : '#f8f9fa',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True,
),
html.Div(id='output-data-upload'),
]),
value="import"),
dmc.TabsPanel("Settings tab content", value="connectbd"),
dmc.TabsPanel("Settings tab content", value="explore"),
],
#color="black",
orientation="horizontal",
)
]
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
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' 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)),
dash_table.DataTable(
df.to_dict('records'),
[{'name': i, 'id': i} for i in df.columns]
),
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-data-upload', '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
Solution attempts: the example of the dcc.Upload is in the documentation , but I use it inside a tab inside a secondary page that is called with the layout function in the app.py. The example is working correctly when is run as it is implemented in the documentation, but I can´t adapt it to my specific use case. I think the problem is near the callback or in the function that outputs the table.
I´m a newbie in dash. Thanks in advance for any help.
Expted: html.Div with uploaded data.

Related

In Dash Plotly how do I upload CSV with dcc.Upload to store using dcc.Store and then display table?

haven’t found a good answer to this issue I am having. Please help!
My goal is to upload CSV via dcc.Upload, store it in dcc.Store, and then display table.
I am taking the code from dcc.Upload tutorial here and inserting a dcc.Store component. The goal is to have two callbacks. The first one would have upload data as input and store as output. The second callback would take store as input and output to a html.Div.
See the code below that is not working. Please help!
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
from dash import dcc, html, dash_table
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
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'
},
# Allow multiple files to be uploaded
multiple=True
),
dcc.Store(id='store'),
html.Div(id='output-data-upload'),
])
#Goal here is to store the csv from upload into dcc.Store
#app.callback(Output('store', 'data'),
Input('upload-data', 'contents'),
State('upload-data', 'filename'),
State('upload-data', 'last_modified'))
def update_output(contents, list_of_names, list_of_dates):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
df = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
return df.to_json(date_format='iso', orient='split') #I have to convert to json format to store in dcc.Store
#Goal here is to then extract dataframe from dcc.store by reading json and output a table
#app.callback(
Output('output-data-upload', 'children'),
Input('store', 'data')
)
def output_from_store(stored_data):
df = pd.read_json(stored_data, orient='split')
return html.Div([
dash_table.DataTable(
df.to_dict('records'),
[{'name': i, 'id': i} for i in df.columns]
),
html.Hr(), # horizontal line
])
if __name__ == '__main__':
app.run_server()
I followed the dcc.Upload tutorial and tried inserting the dcc.Store into it.
Your code was missing a few adjustments to run as expected.
First, as sometimes the values can be inside a list you need to get only the value inside the list, in this case, it's in index 0.
content_string = contents[0].split(',')
Second, to avoid some warnings I have added a condition that will not run the element if the upload values are empty.
if [contents, list_of_names, list_of_dates] == [None, None, None]:
return dash.no_update
You can also use it in your callback declaration:
prevent_initial_call=True
And as a tip, I would suggest you use debug=True n your development environment, so you can have better feedback about what's going wrong, making it easier to debug your code to fix the error
app.run_server(debug=True)
Full code based on your example:
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
from dash import dcc, html, dash_table
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
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'
},
# Allow multiple files to be uploaded
multiple=True
),
dcc.Store(id='store'),
html.Div(id='output-data-upload'),
])
import dash
#Goal here is to store the csv from upload into dcc.Store
#app.callback(Output('store', 'data'),
Input('upload-data', 'contents'),
State('upload-data', 'filename'),
State('upload-data', 'last_modified'),
prevent_initial_call=True)
def update_output(contents, list_of_names, list_of_dates):
if [contents, list_of_names, list_of_dates] == [None, None, None]:
return dash.no_update
content_type, content_string = contents[0].split(',')
decoded = base64.b64decode(content_string)
df = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
return df.to_json(date_format='iso', orient='split') #I have to convert to json format to store in dcc.Store
#Goal here is to then extract dataframe from dcc.store by reading json and output a table
#app.callback(
Output('output-data-upload', 'children'),
Input('store', 'data'),
prevent_initial_call=True
)
def output_from_store(stored_data):
df = pd.read_json(stored_data, orient='split')
return html.Div([
dash_table.DataTable(
df.to_dict('records'),
[{'name': i, 'id': i} for i in df.columns]
),
html.Hr(), # horizontal line
])
if __name__ == '__main__':
app.run_server(debug=True)
I hope it can be helpful for you.
Regards,
Leonardo

Plotly-dash - update graphs in tabs

I like to put plotly graph1 in tab1 and graph2 in tab 2, but there is no trace visible.
Why are traces not visible?
The graph in tab2 is also showing no traces.
It would be great to know whats wrong.
Simular example code would also be a big help.
Many thanks
''' import pandas as pd
import numpy as np
import plotly.express as px
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import requests
import dash_bootstrap_components as dbc
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
#fig1 = px.line(title='title1')
#fig2 = px.line(title='title2')
app.layout = dbc.Container(fluid=True, children=[
html.H1('Title',id="Titel",className='ml-1',style={'text-align': 'center', 'font-weight': 'bold', 'text-decoration': 'underline'}),
## Body
dbc.Row([
dbc.Col(md=6,children=[
html.Br(),html.Br(),
dbc.Col(md=9, children=[
dbc.Col(html.H4("graphs in tabs"), width={"size":6,"offset":3}),
dbc.Tabs(className="nav nav-pills", children=[
dbc.Tab(dcc.Graph(id="grafiek1"), label="tab1"),
dbc.Tab(dcc.Graph(id="grafiek2"), label="tab2")
])
])
#html.Div(id="tab-content", className="mx-auto"), #m=marge p=padding 0-5 of auto vb: P-4
]), # einde kolom 1
dbc.Col(md=6,children=[
]), # einde kolom 2
]), #einde rij
])
#,style={"background-image": 'url(image)'})
#app.callback(
Output("grafiek1", "figure"),
[Input("tabs", "active_tab")])
def tab_content(active_tab):
if active_tab is not None:
if active_tab == "tab1":
fig1 = go.Figure()
fig.add_trace(go.Scatter(x=df['Date'], y=df['AAPL.Low'], mode='markers', name='data', line={"color":"black"}))
## add slider
fig.update_xaxes(rangeslider_visible=True)
## set background color
fig.update_layout(plot_bgcolor='white', autosize=False, width=1000, height=550)
return fig1
#app.callback(
Output("grafiek2", "figure"),
[Input("tabs", "active_tab")])
def tab_content(active_tab):
if active_tab is not None:
if active_tab == "tab2":
fig2 = go.Figure()
fig.add_trace(go.Scatter(x=df['Date'], y=df['AAPL.High'], mode='markers', name='data', line={"color":"black"}))
## add slider
fig.update_xaxes(rangeslider_visible=True)
## set background color
fig.update_layout(plot_bgcolor='white', autosize=False, width=1000, height=550)
return fig2
if __name__ == '__main__':
app.run_server(debug='True')
'''
The 'tabs' id you reference in your callbacks doesn't exist in your layout. Dash doesn't tell you about this because you do this
app.run_server(debug='True')
instead of
app.run_server(debug=True)
You also check if active_tab equals "tab1" in the first callback and "tab2" in the second, but the active_tab prop of your Tabs component isn't set to either of these values. The default active_tab value for the first tab is actually tab-0.
active_tab (string, optional): The tab_id of the currently active tab. If tab_id has not been specified for the active tab, this will default to tab-i, where i is the index (starting from 0) of the tab.
https://dash-bootstrap-components.opensource.faculty.ai/docs/components/tabs/
Since this if statement fails nothing is returned from either callback.
Also the callback function have the same function name, this is not allowed.
Lastly in both callbacks you create a figure, but you add the trace to another figure, so the trace also doesn't show up because you're returning an empty figure.
So instead you could do something like this:
import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import plotly.graph_objects as go
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv"
)
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Container(
fluid=True,
children=[
html.H1(
"Title",
id="Titel",
className="ml-1",
style={
"text-align": "center",
"font-weight": "bold",
"text-decoration": "underline",
},
),
dbc.Row(
[
dbc.Col(
md=6,
children=[
html.Br(),
html.Br(),
dbc.Col(
md=9,
children=[
dbc.Col(
html.H4("graphs in tabs"),
width={"size": 6, "offset": 3},
),
dbc.Tabs(
id="tabs",
className="nav nav-pills",
children=[
dbc.Tab(
label="tab1",
children=[dcc.Graph(id="grafiek1")],
),
dbc.Tab(
label="tab2",
children=[dcc.Graph(id="grafiek2")],
),
],
),
],
),
],
),
dbc.Col(md=6, children=[]),
]
),
],
)
#app.callback(Output("grafiek1", "figure"), [Input("tabs", "active_tab")])
def tab_content1(active_tab):
if active_tab is not None:
if active_tab == "tab-0":
fig1 = go.Figure()
fig1.add_trace(
go.Scatter(
x=df["Date"],
y=df["AAPL.Low"],
mode="markers",
name="data",
line={"color": "black"},
)
)
return fig1
return go.Figure()
#app.callback(Output("grafiek2", "figure"), [Input("tabs", "active_tab")])
def tab_content2(active_tab):
if active_tab is not None:
if active_tab == "tab-1":
fig2 = go.Figure()
fig2.add_trace(
go.Scatter(
x=df["Date"],
y=df["AAPL.High"],
mode="markers",
name="data",
line={"color": "black"},
)
)
# add slider
fig2.update_xaxes(rangeslider_visible=True)
# set background color
fig2.update_layout(
plot_bgcolor="white", autosize=False, width=1000, height=550
)
return fig2
return go.Figure()
if __name__ == "__main__":
app.run_server(debug=True)

How Dynamically populate the DropDown from the data uploaded through Plotly Dash dcc upload option

I have uploaded the data using Plotly Dash dcc upload option. I am not able to dynamically populated the unique columns of uploaded dataframe as part of DropDown
I am able to successfuly upload the file using dcc upload option; i am able to see the output in dash table. but using same input, i am not able to see the output from dropdown.
the dataframe, i have uploaded with the columns of (country, continent, population)
i should able to get the unique columns dropdown
this is my code:
import base64
import datetime
import io
import plotly.graph_objs as go
import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_table
import dash_table_experiments as dte
from dash.dependencies import Input, Output, State
import pandas as pd
app = dash.Dash()
app.layout = html.Div([
html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
multiple=True
),
html.Div(id='output-data-upload'),
])
dcc.Tab(label='Discrete Info', children=[
html.Div([
dcc.Dropdown(
id='select_column',
),
]),
html.Div([
dcc.Graph(
id='bar1',
hoverData={'points': [{'customdata': ''}]},
)
], style={'width': '100%', 'display': 'inline-block', 'padding': '0 10'}),
]),
])
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
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' 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)),
dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'name': i, 'id': i} for i in df.columns]
),
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-data-upload', '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('select_column', 'options'
[Input('output-data-upload', 'children'')]
def dd_update (options)
return(options)
This is a little tricky without specific code to reference, but the basic idea is to set up a callback that will update the options prop of your dcc.Dropdown. You can have that callback triggered (Input) by the upload, make it read in the dataframe, obtain the columns, and then output the properly formatted list of dictionaries.
Please use a following simple example that solves your problem
import base64
import io
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from dash.dependencies import Input, Output
app = dash.Dash()
app.layout = html.Div([
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'
},
),
dcc.Dropdown(
id='dropdown',
options=[],
value=None),
])
def parse_data(contents, filename):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV or TXT file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
elif 'txt' or 'tsv' in filename:
# Assume that the user upl, delimiter = r'\s+'oaded an excel file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')), delimiter = r'\s+')
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return df
#app.callback(
Output('dropdown', 'options'),
[Input('upload-data', 'contents'),
Input('upload-data', 'filename')])
def update_options(contents, filename):
if contents:
df = parse_data(contents, filename)
df = df.set_index(df.columns[0])
lst = [{'label': i, 'value': i} for i in df.columns]
return lst
else:
return []
if __name__ == '__main__':
app.run_server(debug=True)
Here is my working code, very basic, that you can use as a reference
html.Div(children=[
html.Div(children=[
dcc.Dropdown(id='dropdown_students_cols', options=[{'label': i, 'value': i} for i in list(filter(lambda x: x!='userid', list(df)))], value='component'),
]),
html.Div(children=[
dcc.Dropdown(id='dropdown_row_names'),
]),
])
#app.callback(
Output(component_id='dropdown_row_names', component_property='options'),
[Input(component_id='dropdown_students_cols', component_property='value')],)
def get_row_names(column_name='component'):
row_names = df[column_name].unique().tolist()
lst = [{'label': i, 'value': i} for i in row_names]
print(lst)
return lst
The print statement in the callback returns a list of dictionaries that I can use for options:
[{'label': 'mod_glossary', 'value': 'mod_glossary'}, {'label': 'mod_quiz', 'value': 'mod_quiz'},...]
Don't pay attention to lambda function in the original dropdown id='dropdown_students_cols', I just needed to exclude this column from selection.
When you make selection in the original dropdown id='dropdown_students_cols', it invokes the callback function with the selection as an argument.
This selection gives me a required column in the df and then I build a list of unique rows in this column.
Then I iterate over this list to build a list of dictionaries with label:value
The print statement confirms that the list is built successfully
Then I return that list as options for the child dropdown id='dropdown_row_names'
So you can use another trigger as Input, in your case Upload, pass values into the callback, process the data as you need and then return a list if dictionaries as options for the dropdown.
I suggest you trim your code to a vary basic working example and then slowly build up from it.

Strange bug downloading data using app.server.route: filename not updating

This is a very strange bug with plotly dash: downloaded files are not updated even when the source code is changed. I am using Mac OS X, and find the bug when using chrome or firefox but it works correctly using safari. The problem is that the downloaded file does not change after the code is updated.
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import numpy as np
import flask
import io
from dash.dependencies import Input, Output, State
# import plotly.graph_objs as go
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Dropdown(
id='dropdown',
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': 'Montreal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'}
],
value='NYC'
),
html.A('Download',
id='download',
href=''),
# dcc.Store(id='data_store',storage_type='memory'),
])
# Calculate the data and store it.
#app.callback(
Output('download', 'href'),
[Input('dropdown', 'value')])
def update(value):
return '/download_csv/get_it?value={}'.format(value)
#app.server.route('/download_csv/get_it')
def download_excel():
param = flask.request.args
print(param)
# Dummy dataframe for downloading.
d = {'col1': param['value'],'col2': 'Did it change?'}
df = pd.DataFrame(data=d,index=[0])
#Convert DF
str_io = io.StringIO()
df.to_csv(str_io, sep=",")
mem = io.BytesIO()
mem.write(str_io.getvalue().encode('utf-8'))
mem.seek(0)
str_io.close()
return flask.send_file(mem,
mimetype='text/csv',
attachment_filename='downloadFile.csv',
as_attachment=True)
if __name__ == '__main__':
app.run_server(debug=True)
Running this file, we are able to download a csv. However, when using chrome, if the attachment_filename is changed to 'donwloadFile_new.csv' and the download button is pressed again, I still get 'donwloadFile.csv' as the downloaded file! Also, the contents of the downloaded file don't change either.
However, in safari the download function works as expected: file names and contents are updated.
I just answered a similar question here.
you need to specify the cache_timeout parameter in send_file function.

plotly dash: How to get headline of csv as options for dropdown

I am writing a dash-app.
At the moment my app looks like this
`
import base64
import io
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import matplotlib.pyplot
from dash.dependencies import Input, Output
import dash_table_experiments as dt
import numpy as np
app = dash.Dash()
app.scripts.config.serve_locally = True
app.layout = html.Div([
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'
},
# Allow multiple files to be uploaded
multiple=True
),
#plot dropdowns graph and tabel
html.Div(id='output-data-upload'),
html.Div(dt.DataTable(rows=[{}]), style={'display': 'none'}),
],
)
#%%methodes
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
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')),sep=';',header=6)
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded),sep=';',header=6)
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
available_indicators=list(df)
ind =np.delete(available_indicators,0),
print (ind)
return html.Div([
#x-Achse
html.Div('Choose Data for x-axis'),
dcc.RadioItems(
id='x_Achse',
options=[
{'label': i, 'value': i} for i in ind[0]],
),
#y-Achse
html.Label('Choose Data for y-axis'),
dcc.Dropdown(
id='y-Achse',
options=[
{'label': i, 'value': i}for i in ind[0]],
multi= True
),
#Graph
return_graph(df,1,1),
html.H5(filename),
# Use the DataTable prototype component:
# github.com/plotly/dash-table-experiments
dt.DataTable(rows=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'
})
])
#%%
def return_graph(df, x_Werte, Y_Werte_Array):
return dcc.Graph(id='Liniendiagramm',
figure={
'data': [go.Scatter(
x=df['Date/Time'], #change to x_Werte
y=df['Var_01'], #change to Y_Werte_Array[0]
text=df['Var_01'], #change to Y_Werte_Array[0]
name='Var_01' #change to Y_Werte_Array[0]
),
go.Scatter(
x=df['Date/Time'], #change to x_Werte
y=df['Var_02'], #change to Y_Werte_Array[1]
text=df['Var_02'], #change to Y_Werte_Array[1]
name='Var_02' #change to Y_Werte_Array[1]
),
]
}
)
#%%
#end Methoden
#%%callback
#app.callback(Output('output-data-upload', 'children'),
[Input('upload-data', 'contents'),
Input('upload-data', 'filename'),
Input('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
#%%
if __name__ == '__main__':
app.run_server(debug=True)`
Now my Problem.
The dropdowns in my app are in the methode parse_contents. So I get an error, if I try to use a callback to get the value of the dropdowns. The options for the dropdowns are calculate amongst other things in this methode.
I need a solution to get the headline of a Tabel in a .csv flie. Use the values of the headline as options for the dropdowns and write the selected Values of the dropdowns in the methode return_graph .
Finaly it's has to look so
enter image description here
but at the moment the both dropdowns are useless and the graph is ploted by static values
Sorry for the german words in the code, and the bad english.
So now I have a solution for my problem. If Someone want to use it, here is the code. Please note, that in the methode "parse content" the parameters sep=';' and header=6 lines, are set as static parameters.
`import base64
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import dash_table_experiments as dte
from dash.dependencies import Input, Output
import dash
import pandas as pd
import io
app = dash.Dash()
app.scripts.config.serve_locally = True
app.config['suppress_callback_exceptions'] = True
app.layout = html.Div([
html.H5("Upload Files"),
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.Br(),
html.Div("X_Achse"),
dcc.Dropdown(id='x_Achse',
multi = False,
placeholder='Filter Column'),
html.Div('Y_Werte'),
dcc.Dropdown(id='y_Achse',
multi = True,
placeholder='Filter Column'),
html.Div(id='graph'),
html.Br(),
html.H5("Updated Table"),
html.Div(dte.DataTable(rows=[{}], id='table'))
])
# Functions
#%%
# file upload function
def parse_contents(contents, filename):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')),sep=';',header=6)
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded),sep=';',header=6)
except Exception as e:
print(e)
return None
return df
#%%
def return_graph(df, x_Werte, Y_Werte_Array):
return dcc.Graph(id='Liniendiagramm',
figure={
'data': [ #definiert die Daten welche visualisiert werden sollen
go.Scatter(
x=df[x_Werte],
y=df[Y_Werte_Array[i]],
text=df[Y_Werte_Array[i]],
name=Y_Werte_Array[i]
)
for i in range(0,len(Y_Werte_Array))
]
}
)
#%%
#app.callback(Output('graph','children'),
[Input('x_Achse','value'),
Input('y_Achse','value'),
Input('table','rows')])
def update_graph(x,y,c):
if x and y and c is not None:
print (x)
print (y)
# print (c)
dff = pd.DataFrame.from_dict(c)
# print('anfang')
# print(dff)
# print ('ende')
graph1=return_graph(dff,x,y)
# print (c)
return graph1 #return_graph(c,a,b)
#%%
# callback table creation
#app.callback(Output('table', 'rows'),
[Input('upload-data', 'contents'),
Input('upload-data', 'filename')])
def update_output(contents, filename):
if contents is not None:
df = parse_contents(contents, filename)
if df is not None:
# print (df)
return df.to_dict('records')
else:
return [{}]
else:
return [{}]
#%%
#callback update options of filter dropdown
#app.callback(Output('x_Achse', 'options'),
[Input('table', 'rows')])
def update_x_Achse( tablerows):
if tablerows is not None:
dff = pd.DataFrame(tablerows) # <- problem! dff stays empty even though table was uploaded
print ("updating... dff empty?:"), dff.empty #result is True, labels stay empty
return [{'label': i, 'value': i} for i in sorted(list(dff))]
#%%
#app.callback(Output('y_Achse', 'options'),
[Input('table', 'rows')])
def update_y_Achse( tablerows):
if tablerows is not None:
dff = pd.DataFrame(tablerows) # <- problem! dff stays empty even though table was uploaded
print ("updating... dff empty?:"), dff.empty #result is True, labels stay empty
return [{'label': i, 'value': i} for i in sorted(list(dff))]
#%%
app.css.append_css({
"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"
})
if __name__ == '__main__':
app.run_server(debug=True)`