Hello everyone!
When i was doing an interface which dynamically create buttons after an upload of multiple pictures using dcc.Upload, i noticed only the last file treated have the buttons active. The other files have the interface layout correctly adjoined, but none of the callback works.
So i would like to know how to properly handle having multiple pictures uploaded using dcc.Upload so i can interact with all pictures.
Here is my code (simplified) to reproduce the problem (simply upload 2 pictures and try to click on the buttons) :
from dash import Dash, html, dcc
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc
import base64
import numpy as np
#CSS
external_stylesheets=[dbc.themes.BOOTSTRAP]
#app
app = Dash(__name__,external_stylesheets=external_stylesheets,suppress_callback_exceptions=True)
#layout
app.layout = html.Div([
dcc.Upload(
id='upload-image',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '70%',
'height': '60px',
'justify':'center',
'text-align':'center',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '500px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
html.Div(id='output-image-upload'),
])
#callback upload button
@app.callback(Output('output-image-upload', 'children'),
Input('upload-image', 'contents'),
State('upload-image', 'filename'),
State('upload-image', '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
def parse_contents(contents,unused,unused2):
content_type, content_string = contents.split(",")
decoded = base64.b64decode(content_string)
jpg_as_np = np.frombuffer(decoded, dtype=np.uint8)
import random
result = random.randrange(1000)
return html.Div([
dcc.Store(id='store-picture',data=result),
html.Br(),
dbc.Row([
dbc.Col(
html.Img(
src=contents,
style={
'margin-left':'auto',
'margin-right':'0px',
'width':'40%',
'padding-left':'20px'}),
),
dbc.Col(
html.Div(result,
style={
'font-size':'40px',
'padding-top':'10px',
'font-weight':'bold',
'font-family':'courier',
}
)
),
dbc.Col([
dbc.Row(html.Div('Is the prediction correct?')),
dbc.Row([
dbc.Col(
html.Button('Yes',id='button-pred-yes',n_clicks=0)
),
dbc.Col(
html.Button('No',id='button-pred-no',n_clicks=0)
)
]),
dbc.Row(
html.Div(id='div-prediction-result')
)
])
])
])
@app.callback(
Output('div-prediction-result','children'),
[Input('button-pred-yes','n_clicks'),Input('button-pred-no','n_clicks')],
[State('store-picture','data')]
)
def confirm_prediction(bpy,bpn,data):
prediction = data
if bpy:
return prediction
elif bpn:
return prediction
#--------- LAUNCHER ------------
if __name__ == '__main__':
app.run_server(debug=True)