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?