这个问题是下面链接的问题的扩展:
Dash Python:布局函数中的@Callback未被调用
我有一个简单的数据框:
import pandas as pd
df = pd.DataFrame({'Class1': [1, 2, 3, 4, 5],
'Class2': [6, 7, 8, 9, 10]}
)
我创建了一个数据提取函数,该函数根据列的位置。
data_extraction.py
def dataExtraction(arg1):
df = pd.DataFrame({'Class1': [1, 2, 3, 4, 5],
'Class2': [6, 7, 8, 9, 10]}) ## <-- or Import df from somewhere
df = df[[f'Class{arg1}']]
return df
tab_page.py
import layout as lay
import data_extraction as de
import dash_bootstrap_components as dbc
from dash import html, Dash
import dash
app = Dash()
dash.register_page(__name__,
path='/tabs')
def get_layout(position):
df = de.dataExtraction(position)
layout = lay.update_page(position, df)
return layout
tab1_content = dbc.Card(
dbc.CardBody(
[
get_layout(1)
]
),
className="mt-1",
)
tab2_content = dbc.Card(
dbc.CardBody(
[
get_layout(2)
]
),
className="mt-2",
)
layout = html.Div(children = [
dbc.Tabs(
[
dbc.Tab(tab1_content, label="1",activeLabelClassName="text-success"),
dbc.Tab(tab2_content, label="2",activeLabelClassName="text-success"),
]
)])
app.layout = [layout]
lay.create_callback(1)
lay.create_callback(2)
if __name__ == '__main__':
app.run(debug=True)
layout.py
from dash import dcc, html, Input, Output, callback
from dash import Dash, dash_table, State
import dash_daq as daq
import pandas as pd
def update_page_test(arg1, arg2):
layout = html.Div(children=[html.H1(f'Class {arg1}'),
daq.NumericInput(
id=f'numericinput{arg1}',
min=0,
max=100,
value=0, )
, html.Br(),
dash_table.DataTable(
id=f'tableTest{arg1}',
data=arg2.to_dict('records'),
columns=[{"name": i, "id": i} for i in arg2.columns]),
dcc.Store(id=f'{arg1}mystore', data=[],storage_type='memory'),
])
return layout
def create_callback(i):
@callback(
Output(f'tableTest{i}', 'data'),
Input(f'numericinput{i}', 'value'),
State(f'tableTest{i}', 'data'),
State(f'{i}mystore', 'data'),
)
def updateTableTest(x,data, Orig):
data = pd.DataFrame(data)
Orig = pd.DataFrame(Orig)
if x > 0:
print(f'Callback for class {i} works')
data.iloc[:,1:] = Orig.iloc[:,1:]*x
return data.to_dict('records')
return Orig.to_dict('records')
return updateTableTest
我想构造一个包含 3 个选项卡的页面的选项卡页。像这样的事情:
...
total_content = dbc.Card(
dbc.CardBody(
[
html.Div([
html.Div(id='table-placeholder', children=[])
], className='row')
]
),
className="mt-3",
)
layout = html.Div(children = [
dbc.Tabs(
[
dbc.Tab(tab1_content, label="1",activeLabelClassName="text-success"),
dbc.Tab(tab2_content, label="2",activeLabelClassName="text-success"),
dbc.Tab(total_content, label="total",activeLabelClassName="text-success"),
]
),
])
问题: 我如何能够更新layout.py部分,以便总计选项卡使用其他选项卡总和中的数据进行更新,并且当数字输入框调整时总计也会更新更新?
例如,如果选项卡 1:[1,2,3] 选项卡 2:[4,5,6] -> 总计:[5,7,9]。如果选项卡 1 中的数字输入框设置为 2,则结果将为选项卡 1: [2,4,6] 选项卡 2: [4,5,6] -> 总计:[6,9,12]
我正在考虑使用另一个回调选项来更新每个选项卡中的存储数据,然后将其输出到总选项卡中,但我不确定这将如何工作。我已经尝试过这个,但我被卡住了:
def update_store(i):
@callback(
Output(f'{i}mystore', 'data'),
Input(f'tableTest{i}', 'data'),
)
def Update(data):
print(f'Callback update store {i} works')
print(data)
return data
return Update
def output_total(i):
@callback(
Output('table-placeholder', 'children'),
State(f'{i}mystore', 'data'),
)
def create_total_table(data):
print(f'Callback of create Total {i} works')
return data
return create_total_table
好的,我们可以通过一些调整来实现这个功能。以下是如何使用回调函数和
dcc.Store
组件链接选项卡以计算总和的示例:
1. 修改
layout.py
:
from dash import dcc, html, Input, Output, callback
from dash import Dash, dash_table, State
import dash_daq as daq
import pandas as pd
def update_page_test(arg1, arg2):
layout = html.Div(children=[
html.H1(f'Class {arg1}'),
daq.NumericInput(
id=f'numericinput{arg1}',
min=0,
max=100,
value=0,
),
html.Br(),
dash_table.DataTable(
id=f'tableTest{arg1}',
data=arg2.to_dict('records'),
columns=[{"name": i, "id": i} for i in arg2.columns]
),
dcc.Store(id=f'{arg1}mystore', data=arg2.to_dict('records'), storage_type='memory'),
])
return layout
def create_callback(i):
@callback(
[Output(f'tableTest{i}', 'data'),
Output(f'{i}mystore', 'data')],
Input(f'numericinput{i}', 'value'),
State(f'{i}mystore', 'data')
)
def updateTableTest(x, data):
data = pd.DataFrame(data)
if x > 0:
print(f'Callback for class {i} works')
data.iloc[:, 1:] = data.iloc[:, 1:] * x
return data.to_dict('records'), data.to_dict('records')
return updateTableTest
def create_total_callback():
@callback(
Output('table-placeholder', 'children'),
[Input('1mystore', 'data'), Input('2mystore', 'data')]
)
def update_total_table(data1, data2):
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
df_total = df1.add(df2)
total_table = dash_table.DataTable(
id='tableTotal',
data=df_total.to_dict('records'),
columns=[{"name": i, "id": i} for i in df_total.columns]
)
return total_table
return update_total_callback
2. 修改
tab_page.py
:
import layout as lay
import data_extraction as de
import dash_bootstrap_components as dbc
from dash import html, Dash
import dash
app = Dash(__name__)
dash.register_page(__name__,
path='/tabs')
def get_layout(position):
df = de.dataExtraction(position)
layout = lay.update_page_test(position, df)
return layout
tab1_content = dbc.Card(
dbc.CardBody(
[
get_layout(1)
]
),
className="mt-1",
)
tab2_content = dbc.Card(
dbc.CardBody(
[
get_layout(2)
]
),
className="mt-2",
)
total_content = dbc.Card(
dbc.CardBody(
[
html.Div([
html.Div(id='table-placeholder', children=[])
], className='row')
]
),
className="mt-3",
)
layout = html.Div(children=[
dbc.Tabs(
[
dbc.Tab(tab1_content, label="1", activeLabelClassName="text-success"),
dbc.Tab(tab2_content, label="2", activeLabelClassName="text-success"),
dbc.Tab(total_content, label="total", activeLabelClassName="text-success"),
]
),
])
app.layout = layout
lay.create_callback(1)
lay.create_callback(2)
lay.create_total_callback()
if __name__ == '__main__':
app.run_server(debug=True)
解释:
-
update_page_test
函数:-
我们不再需要
update_store
函数,因为我们在create_callback
中直接更新dcc.Store
。
-
我们不再需要
-
create_callback
函数:-
现在,它同时输出到
tableTest{i}
和f'{i}mystore'
,以保持数据同步。
-
现在,它同时输出到
-
create_total_callback
函数:-
这个新函数创建了一个回调函数,用于监听两个
dcc.Store
组件的变化。 -
当任何一个选项卡的数据发生变化时,它会读取两个
dcc.Store
的数据,计算总和,并更新 “Total” 选项卡中的表格。
-
这个新函数创建了一个回调函数,用于监听两个
现在,的应用程序应该能够在每个选项卡中显示数据,并在 “Total” 选项卡中显示它们的总和,并且当更改数字输入框时,总和会相应更新。
标签:python,callback,plotly,plotly-dash From: 78840847