提问人:Alex M 提问时间:9/24/2023 更新时间:9/24/2023 访问量:77
Dash 多页面应用无法检测到不同页面布局中的回调输出 ID
Dash multi-page app failing to detect callback output IDs in different page layouts
问:
我正在尝试将我的多选项卡仪表板重新配置为多页应用程序,但遇到回调输出错误的问题。
以下是我如何模块化以跟踪应用程序的组件:
文件夹结构
- app.py
- assets
- data_processing_scripts
- app_scripts
- app_pages
|-- __init__.py
|-- home.py
|-- data_upload.py
|-- visualisation.py
|-- about.py
- app_tabs
- data_upload_tabs
|-- software_1_tables_upload.py
- data_visualisation_tabs
|-- software_1_data_visualisation.py
- app_data_store
|-- data_store_software_1.py
- callbacks
|-- all_callbacks.py
|-- software_1_data_callbacks.py
- navigation_bar
|-- nav_bar.py
我使用 dash-uploader 库将多个表作为压缩文件上传到页面中。在这里,键入 dash-uploader 事件的初始回调会创建一系列输出,这些输出用作处理数据处理和最终绘图生成的其他回调的输入。然后,应将这些绘图和表格提供给应用程序,以便在可视化页面的各个子选项卡中显示。data_upload
页面只是定义页面总体布局的包装器。我从文件夹中的模块导入函数,这些模块返回布局的内容,即上传或可视化页面。这些布局引用各种回调输出 ID。html.Div()
app_tabs
我对回调遵循了相同的逻辑。 从 导入回调。和被导入到其中,用于实例化应用。all_callbacks.py
software_1_data_callbacks.py
pages
all_callbacks
app.py
我使用各种对象,这些对象将各种表作为回调的输入传递。在这里,我将它们包装在一个函数中,但不是将它们放在布局上的隐藏 div 中,而是将它们导入到 .dcc.Store
data_store_software_1.py
data_upload
app.py
通过这种方式,我在 中引用了应用程序的所有必要部分。这种模块化适用于具有选项卡和嵌套子选项卡的单页应用。app.py
是的,如果你在介绍之后还没有关闭,这是我的设置方式:app.py
# =============================================================================
import dash_uploader as du
import dash_bootstrap_components as dbc
import dash
from dash import html
# =============================================================================
from app_scripts.navigation_bar.nav_bar import create_navbar
from app_scripts.callbacks.all_callbacks import all_callbacks
from app_scripts.app_data_store.maxquant_data_store import data_store_software_1
# =============================================================================
#### Define app.
app = dash.Dash(__name__,
suppress_callback_exceptions = True,
prevent_initial_callbacks = True,
pages_folder = './app_scripts/app_pages',
use_pages = True,
external_stylesheets = dbc.themes.BOOTSTRAP)
#### Define server.
server = app.server
# --------------------------------------------------------------------------- #
#### Configure uploader.
du.configure_upload(app,
r'C:\tmp\data_uploads',
use_upload_id = True)
# --------------------------------------------------------------------------- #
#### Generate navigation bar.
nav_bar = create_navbar()
# --------------------------------------------------------------------------- #
#### Generate layout.
app.layout = html.Div(
style = {'background': '#f0f0f0'},
children = [
data_store_software_1(),
nav_bar,
dash.page_container
]
)
# --------------------------------------------------------------------------- #
#### Specify callbacks.
all_callbacks(app)
# --------------------------------------------------------------------------- #
#### Instantiate app.
if __name__ == '__main__':
app.run_server(debug = True,
dev_tools_hot_reload = False)
# --------------------------------------------------------------------------- #
什么有效:
该应用程序完全按照我的预期呈现。页面路由正确,各个页面和子选项卡的布局都显示正确无误。
什么不起作用:
回调输出 ID 错误:
A nonexistent object was used in an `Output` of a Dash ...
根据我导航到的页面,错误引用另一个页面布局中的回调输出 ID,反之亦然。我可以从堆栈跟踪中看到哪些 ID 在我单击的页面布局中:
The string ids in the current layout are: [list of ID's]
糟糕的解决方案
我必须同时调用页面布局。在这种情况下,我还必须包含每个回调输出 ID 的对象,包括绘图(各种绘图图形、绘图 png、pandas 样式表)。最终效果是,绘图在页面中的渲染速度非常慢,以至于无法使用,有时还会由于达到内存限制而引发浏览器错误。此外,单击并返回可视化页面,再次启动绘图渲染过程...慢慢。在我的标准 1 页方法中,只有表和字符串变量。data_store_software_1
data_upload
visualisation
dcc.Store(id = 'some_callback_out')
visualisation
dcc.Store()
我试过了什么
1 - 从这里开始的最小示例 - https://github.com/AnnMarieW/dash-multi-page-app-demos/tree/main/multi_page_store
我使用这种方法时,将 直接传递给 中的应用程序布局。这会导致上述错误。data_store_software_1
app.py
2 - 尝试验证 - https://dash.plotly.com/urls#dynamically-create-a-layout-for-multi-page-app-validation
在本例中,布局如下所示:app.py
app_contents = html.Div(
style = {'background': '#f0f0f0'},
children = [
nav_bar,
dash.page_container]
)
app.layout = app_contents
app.validation_layout = html.Div(children = [
data_store_software_1(),
app_contents]
)
这里的错误仍然是:
A nonexistent object was used in an `Output` of a Dash ...
只不过它只是dash_uploader的第一个回调输出 ID。如果我随后将此 ID 添加到它,只需指定另一个 ID 等,因此再次回到方块 1。data_store_software_1()
3 - 可能是我遇到的问题的最接近的例子:
在这里,我无法弄清楚如何按照建议拆分我的回调。仅将存储用于特定布局也会导致各种输出 ID 错误。
问题
显然,我看不到树木的树林,或者也许不能像我想象的那样完成。
我怎样才能解决这个问题?
非常感谢您抽出时间,很抱歉冗长的解释。我还想生成一个最小工作的例子,使用我的总体方法复制这个错误。最后,我认为描述性方法可能会更好,因为我不知道如何在这种情况下重新创建一个独立的 dash-uploader 实例。
答: 暂无答案
评论
url
Input('url', 'href')
@callback([Output('table_2', 'data'), Output('table_3', 'data')], [State('ID_string', 'data'), State('table_1', 'data')])
Output
State
callback
Input
State
Output