Hotone
Hotone

Reputation: 453

Populate a dash_table from a dataframe after clicking a button in dash

I have started looking at dash/plotly and can't figure out what I am doing wrong. I would like to update a div with dash_table via a callback. The data is coming from a pandas dataframe/db query

I tried to trim the code down to the minimum

import dash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Output, Input, State

import datetime
import re
import pandas as pd

import plotly.graph_objects as go

app = dash.Dash()

app.layout = html.Div(children=[html.Div("Dashboard",
                                     style={"color": "white", "text-align": "center", "background-color": "blue", "display": "inline-block", "width": "100%", "font-size": "46px",
                                            }),
                            dcc.Tabs([
                                dcc.Tab(label='Upcoming events',
                                        children=[
                                            html.Div("Select a period: ",
                                                    style={"text-align": "center"}),
                                            html.Div(
                                                dcc.DatePickerRange(
                                                    id="calendar_period",
                                                    start_date_placeholder_text="Start Period",
                                                    end_date_placeholder_text="End Period",
                                                    start_date=datetime.datetime.today(),
                                                    end_date=datetime.datetime.today(),),
                                                style={"text-align": "center"}
                                            ),
                                            html.Div(
                                                html.Button("Retrieve calendar", id="submit_period", n_clicks=0),
                                                style={"text-align": "center"}
                                            ),
                                            html.H1(id='calendar_table'),
                                        ]),
                                dcc.Tab(label='Some other tab',)
                                ])
                            ])


@app.callback(
[Output('calendar_table', 'children')],
[Input('calendar_period', 'start_date'), Input('calendar_period', 'end_date')],
[State('submit_period', 'n_clicks')])

def retrieve_calendar(start_date, end_date, n_clicks):
    events = pd.read_sql_query(...) #<- query based on start_date and end_date both in date format
    columns = [{"name": i, "id": i, } for i in events.columns]
    df_data = events.to_dict('rows')


    return dash_table.DataTable(data=df_data, columns=columns)


if __name__ == '__main__':
    app.run_server(debug=True)

When running the file and going onto 127.0.0.1:8050, I have my date range picker and can select the dates. I do retrieve the correct date in python. But when I click on the button, nothing is happening. I did a few trials with various start/end dates and the db query returns a dataframe within a few seconds. I also tried to

Input('submit_period', 'n_clicks')

but nothing popping up neither.

Edit: I get the following error message:

The callback ..calendar_table.children.. is a multi-output.

A bit confusing since my callback defines only one output:

Output('calendar_table', 'children')

I added also:

def retrieve_earnings(start_date, end_date, n_clicks):
    events = pd...
                    
    print(events.head())
    columns = [{"name": i, "id": i, } for i in events.columns]
    print(columns)
    df_data = events.to_dict('records')
    print(df_data)

    return dash_table.DataTable(data=df_data, columns=columns)

I get twice

Empty DataFrame

and after 5 seconds or so after launching the programming (minus the time to select a date range) the print(events.head()) is showing the correct data in the Python console but still with the same multi output error and no data table shown on 127.0.0.1

Edit2: I switched State to Input for submit_period button and returned [dash_table.DataTable(...)], this seems to do the "trick" but in this case the submit button is useless...

Upvotes: 3

Views: 4745

Answers (1)

coralvanda
coralvanda

Reputation: 6596

Your callback defines the output as a list with length of 1. Dash considers that to be a multi-output callback. Remove the square brackets ([, ]) and just give it the Output(). That should resolve your error.

Upvotes: 2

Related Questions