Second callback is not working

Hello, I have multiapp, and the project structure is next:

Project
– -apps
– - - app1.py
– - - app2.py
index.py
app.py

There is the code for every of them:

index.py:

import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from app import app
from apps import app1, app2


app.layout = html.Div(
    [dcc.Location(id="url", refresh=False), html.Div(id="page-content")]
)


@app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def display_page(pathname):
    if pathname == "/apps/app1":
        return app1.layout
    elif pathname == "/apps/app2":
        return app2.layout
    else:
        return app1.layout


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

app.py:

import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
from dash.dependencies import Input, Output

external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
server = app.server

app.config.suppress_callback_exceptions = True

app1.py:


import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import data_processor
from app import app
import pandas as pd
import dash_bootstrap_components as dbc
from datetime import datetime as dt
from itertools import islice
import uuid
from flask_caching import Cache


data = data_processor.get_data(
    "overview_critical_calls.csv", 1
)  # There we read the data from first .csv,with Call statistics
data2 = data_processor.get_data(
    "alfa_gewerke_counts.csv", 2
)  # there we read the data from second .csv, with Gewerke

columnnames = [
    "Customer",
    "Calls",
    "Hours",
]  # columns name for the dataframe for 1st file

moderdf = pd.DataFrame.from_records(
    data, columns=columnnames
)  # creation of the dataframe with pandas for the global statistics

# There we describe cache congif
cache = Cache(
    app.server,
    config={
        "CACHE_TYPE": "redis",
        # Note that filesystem cache doesn't work on systems with ephemeral
        # filesystems like Heroku.
        "CACHE_TYPE": "filesystem",
        "CACHE_DIR": "cache-directory",
        # should be equal to maximum number of users on the app at a single time
        # higher numbers will store more data in the filesystem / redis cache
        "CACHE_THRESHOLD": 200,
    },
)

"""
In function below we generate links for every customer.
As input we use data2 (prepared above) and customer name
"""


def prepare_link_data(actions, dataframe, customer):
    arglist = []
    idlist = []
    if actions == 1:
        if customer in dataframe.keys():
            for keys in dataframe[customer].keys():
                tempquantity = dataframe[customer][keys]

                arglist.append(
                    html.A(
                        children=[keys + "(" + tempquantity + ")"],
                        target="_blank",
                        href="/apps/app2",
                        id=customer + "_" + keys,
                    )
                )
                arglist.append("  ")

        return arglist
    elif actions == 2:
        if customer in dataframe.keys():
            for keys in dataframe[customer].keys():

                idlist.append(dcc.Input(id=customer + "_" + keys))

        return idlist


"""
Function below (prepare_table_data) prepare data for the Table we built on the page.
As input we use dataframe, that was prepared before.
"""


def prepare_table_data(action, dataframe, max_rows=26):
    rows = []
    columns = []
    if action == 1:
        for col in dataframe.columns:
            columns.append(html.Th(col))
        rows.append(html.Tr(columns))  # There we prepare headers for the table

        for i in range(min(len(dataframe), max_rows)):
            columns = []

            for col in dataframe.columns:  # There we prepare rows
                if (
                    col == "Customer"
                ):  # We don't need to make dropdown  elements for every cell, only for 1st column

                    columns.append(  # Default color scheme is white background,font is black
                        html.Td(
                            html.Details(
                                [
                                    html.Summary(
                                        dataframe.iloc[i][col],
                                        style={
                                            "backgroundColor": "#ffffff",
                                            "color": "black",
                                        },
                                    ),
                                    *prepare_link_data(
                                        1, data2, dataframe.iloc[i][col]
                                    ),
                                ],
                                style={
                                    "border": "1px solid black",
                                    "border-collapse": "collapse",
                                },
                            )
                        )
                    )
                else:  # This 'else' for all cells that are not included in 1st column

                    columns.append(
                        html.Td(
                            dataframe.iloc[i][col],
                            style={
                                "border": "1px solid black",
                                "border-collapse": "collapse",
                            },
                        )
                    )

            rows.append(
                html.Tr(columns)
            )  # There we append headers for the table and rows

        for elements in islice(
            rows, 1, None
        ):  # in this cycle we change the style of every cell of needed
            if (
                float(elements.children[1].children) >= 11
            ):  # if "Calls" is >=11 - then red
                elements.children[0].children.children[0].style[
                    "backgroundColor"
                ] = "#ff0000"
            elif (
                5 <= float(elements.children[1].children) < 11
            ):  # if 5< = "Calls"<11 - then orange
                elements.children[0].children.children[0].style[
                    "backgroundColor"
                ] = "#ff8000"
            elif (
                3 <= float(elements.children[1].children) < 5
            ):  # if 3 < = "Calls" < 5 - then yellow
                elements.children[0].children.children[0].style[
                    "backgroundColor"
                ] = "#ffff00"

        return rows
    elif action == 2:
        returningids = []
        for i in range(min(len(dataframe), max_rows)):
            for col in dataframe.columns:  # There we prepare rows
                if col == "Customer":
                    a = prepare_link_data(2, data2, dataframe.iloc[i][col])

                    returningids.append(a)

        return returningids



# blue navigation bar on top of the page ( we can add some link in it later)
navbar = dbc.NavbarSimple(brand="Overview", brand_href="", color="primary", dark=True)

# There we prepare body using bootstrap enveloper for dash.
body = dbc.Container(
    [
        dbc.Row(
            [
                dbc.Col(html.Div(children=[], id="experiment")),
                dbc.Col(
                    [
                        html.H1(
                            "Pick date range", id="date_range_header"
                        ),  # Date picker. Need to be replaced
                        dcc.DatePickerRange(
                            id="my-date-picker-range",
                            min_date_allowed=dt(1995, 8, 5),
                            max_date_allowed=dt(2030, 1, 1),
                            initial_visible_month=dt(
                                dt.today().year, dt.today().month, dt.today().day
                            ),
                            end_date=dt(
                                dt.today().year, dt.today().month, dt.today().day
                            ),
                        ),
                        dbc.Button(
                            "Search", id="submit_button", outline=True, color="primary"
                        ),
                        dbc.Button(
                            "Show me", id="show_button", outline=True, color="primary"
                        )
                        # Button, not working
                    ]
                ),
            ]
        )
    ],
    className="mt-4",
)

# hidden layout

hiddenlayout = html.Div(id="hidden_lay", style={"display": "none"}, children=[])


# storage=dcc.Store(id='app1_storage',children=[])

# There we prepare layout for user
def prepare_layout():
    session_id = str(uuid.uuid4())
    return html.Div(
        [
            hiddenlayout,
            navbar,
            body,
            html.Div(session_id, id="session-id", style={"display": "none"}),
        ]
    )


# Creation of the layout for app
# the sequence of the arguments is very important: if navbar will be second, then it will fall down as footer
# layout = html.Div([hiddenlayout,navbar, body, dcc.Input(style={"display": "none"})])
layout = prepare_layout()


# callback for "Search" button click (id = "submit_button)
@app.callback(
    [
        Output(component_id="experiment", component_property="children"),
        Output(component_id="hidden_lay", component_property="children"),
    ],
    [Input(component_id="submit_button", component_property="n_clicks")],
)
def button_clicked(clicked):


    if clicked is not None:
        rows = prepare_table_data(1, moderdf)
        arga = prepare_table_data(2, moderdf)

        flattened = [val for sublist in arga for val in sublist]

        return [html.Table(rows, style={"width": "600px"}), flattened]

    else:
        return ["", ""]


@app.callback(
    Output(component_id="session_id", component_property="children"),
    [Input(component_id="show_button", component_property="n_clicks")],
)
def app2upload(clickss):
    if clickss is not None:
     print("Second callback is working")

So the problem is, that my second callback is not working.
I understand that this is because of the fact that i have multiapp and somewhere something is not rendering,
but I do not know where exactly to search.
Can you help me with this pls?

This may be your problem: See the section All callbacks must be defined before the server starts here (https://dash.plot.ly/faqs)

Hi and thanks for answer, however i replicated structure from guide ( this one: https://dash.plot.ly/urls)
and I believe that it follows this rule

Found solution with my friend’s help again:
in app1.py it was typo in second callback, in Output.
Instead of “session_id” i should have wrote "session-id"

1 Like