Hello the community,
I am trying to build an e-commerce website using dash that can be found https://carrefourcontactfontenilles.herokuapp.com/
The app contains 3 tabs :
- “Catalogue de produits” which is the products catalogue
- “Panier” which will be the basket of the customer
- “Validation commande” which will be to validate the order
Actually I am done with the fist tab “Catalogue de produits”
If you click on it, and use the drop downs present in the navbar you will see the correspond products.
My issue now is that I want to assign a callback for every button “Ajouter” (add) present on each product card, which will update as output the basket list of the customer.
After have read a lot on this forum, I have found the below method to assign a callback having input all the buttons (each button id is the article# present in the column data[‘Article’ ] :
List_button = data['Article'].tolist()
input_list=[Input('{}'.format(tool),'n_clicks_timestamp') for tool in List_button]
@app.callback(Output('session_3','children'),
input_list)
def update_panier2(b_list=[('b{}'.format(tool)) for tool in range(1,len(List_button))]):
try:
INDEX=b_list.index(max(filter(lambda x: x is not None,b_list)))
return html.Div([List_button[INDEX]])
I use an output in a html.div for test purpose to return the reference# of the corresponding product where the button has been clicked, with ‘data’ being my database with more than 6,000 products. I used ‘n_clicks_timestamp’ to identify the latest button clicked.
However doing 6,000 callback in one time make the app impossible to use.
I am trying now to create the button callbacks inside a function which is inside the callback which refresh the product catalogue based on the drop down selection:
#update product list
@app.callback(
[Output('product_list', 'children')
],
[Input('cat1', 'value')])
def update_layout(department):
fi1=data[data['Cat2'] == str(department)]
list_nom=fi1['Name'].tolist()
list_EAN=fi1['EAN'].tolist()
list_pack=fi1['Pack'].tolist()
list_prix=fi1['Prix'].tolist()
list_ref=fi1['Article'].tolist()
#input_list=[Input('{}'.format(tool),'n_clicks_timestamp') for tool in list_ref]
rws= len(fi1)
title="test"
gridLayout = []
card=[]
for r in range(0, rws):
try:
title=list_nom[r]
EAN=list_EAN[r]
Pack = list_pack[r]
Prix = list_prix[r]
Ref = list_ref[r]
image_filename = 'Picture/' + str(EAN) + '.png'
encoded_image = base64.b64encode(open(image_filename, 'rb').read())
card2=dbc.Col([
dbc.Card([
dbc.CardImg(src='data:image/png;base64,{}'.format(encoded_image.decode()), top=True),
dbc.CardBody([
html.H5(title, className="card-title"),
html.P(Pack,className="card-text",),
],
style={"height": "10rem"}),
dbc.Col([dcc.Dropdown(id='demo-dropdown',style={'font-size': "130%"},value=1,options=[{'label': '1', 'value': 1},
{'label': '2', 'value': 2},
{'label': '3', 'value': 3},
{'label': '4', 'value': 4},
{'label': '5', 'value': 5},
{'label': '6', 'value': 6},
{'label': '7', 'value': 7},
{'label': '8', 'value': 8},
{'label': '9', 'value': 9},
{'label': '10', 'value': 10},
],placeholder="Quantité")]),
dbc.Col([dbc.Button('Ajouter',id=str(Ref),color="primary",n_clicks=0)]),
dbc.CardFooter(html.H4('Reference : ' + str(Ref))),
dbc.CardFooter(html.H4(str(Prix) + ' EUR'))
])],md=3,xs=6,sm=6,lg=3,xl=3)
if r!=rws+1:
card.append(card2)
elif r == 1:
card.append(card2)
else:
card.append(",",card2)
except:
title=list_nom[r]
EAN=list_EAN[r]
Pack = list_pack[r]
Prix = list_prix[r]
Ref = list_ref[r]
image_filename = 'Picture/non_dispo2.png'
encoded_image = base64.b64encode(open(image_filename, 'rb').read())
card2=dbc.Col([
dbc.Card([
dbc.CardImg(src='data:image/png;base64,{}'.format(encoded_image.decode()), top=True),
dbc.CardBody([
html.H5(title, className="card-title"),
html.P(Pack,className="card-text",),
],
style={"height": "10rem"}),
dbc.Col([dcc.Dropdown(id='demo-dropdown',value=1,style={'font-size': "130%"},options=[{'label': '1', 'value': 1},
{'label': '2', 'value': 2},
{'label': '3', 'value': 3},
{'label': '4', 'value': 4},
{'label': '5', 'value': 5},
{'label': '6', 'value': 6},
{'label': '7', 'value': 7},
{'label': '8', 'value': 8},
{'label': '9', 'value': 9},
{'label': '10', 'value': 10},
],placeholder="Quantité")]),
dbc.Col([dbc.Button('Ajouter',id=Ref,color="primary")]),
dbc.CardFooter(html.H4('Reference : ' + str(Ref))),
dbc.CardFooter(html.H4(str(Prix) + ' EUR'))
])],md=3,xs=6,sm=6,lg=3,xl=3)
if r!=rws+1:
card.append(card2)
elif r == 1:
card.append(card2)
else:
card.append(",",card2)
fi2=data[data['Cat2'] == str(department)]
List_button = fi2['Article'].tolist()
input_list=[Input('{}'.format(tool),'n_clicks_timestamp') for tool in List_button]
@app.callback(Output('session_3','children'),
input_list)
def update_panier2(b_list=[('b{}'.format(tool)) for tool in range(1,len(List_button))]):
try:
INDEX=b_list.index(max(filter(lambda x: x is not None,b_list)))
return html.Div([List_button[INDEX]])
except:
return html.Div('not working-:(')
c=html.Div(card,className='row')
gridLayout.append(c)
return gridLayout
I have an error on the App
dash.exceptions.DuplicateCallbackOutput:
You have already assigned a callback to the output
with ID “session_3” and property “children”. An output can only have
a single callback function. Try combining your inputs and
callback functions together into one function.
It is my first time using dash and I am blocked. If you have some suggestion on the way I can achieve my objective I thank you in advance
Thank you
David