dash_table.DataTable持久性与navlinks不兼容。

6

在多页面的Dash应用中,我尝试在不同页面之间切换后保留dash_table.DataTable中的值。我已经尝试过使用navlinks(下面是示例代码),pages(dash 2.5版本)和tabs。我想使用持久性参数来实现这一点,而不是使用dcc.Store,并且使用navlinks/pages而不是tabs

似乎刷新页面会覆盖持久性关键字,即使将其设置为“session”或“local”,因为使用选项卡可以解决此问题(选项卡不会刷新页面)。 我还尝试了dcc.Locationrefresh=False但没有成功。我编写了一个小示例代码来显示我的问题。从我的打印语句中,您也可以观察到在切换链接/页面后数据被重置为'None'

import pandas as pd
import numpy as np
from dash import Dash, callback, html, dcc, dash_table, Input, Output, dash_table, callback_context as ctx
import dash_bootstrap_components as dbc


df = pd.DataFrame({'test1':np.zeros(3), 'test2':np.zeros(3)})
def get_data():
    return df

app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions= True)
app.layout = dbc.Container([
    dcc.Location(id = 'url', refresh = False),
    dbc.Row(
        dbc.Navbar(
            dbc.Nav(children=[
                dbc.NavItem(dbc.NavLink("Main", active='exact', external_link=False, href='/'), id = 'main'),
                dbc.NavItem(dbc.NavLink("A link", active = 'exact', external_link=False, href="/link"), id = 'alink')
            ])
        )
    ),
    html.Div(id = 'link')
])
    
main = html.Div([
            dbc.Row(
                dbc.Col([
                    dbc.Button("test1 +1", id='btn1', className="me-2", n_clicks = 0),
                    dbc.Button("test2 +1", id='btn2', className="me-2", n_clicks = 0)
                ])
            ),
            dbc.Row([
                dbc.Col(
                    dash_table.DataTable(columns = [{'name': x, 'id':x} for x in get_data().columns],
                                         id = 'table',
                                         persistence = True, 
                                         persisted_props = ['data'],
                                         persistence_type = 'session')
                )
            ])
    ])

@app.callback(
    Output('link', 'children'),
    Input('url', 'pathname')
)
def render_page(path):
    print(path)
    if path != '/':
        layout = html.Div(
            dbc.Row(
                html.H5(path)
            )
        )
    else:
        layout = main
    return layout

@app.callback(
    Output('table', 'data'),
    [
     Input('table', 'data'),
     Input("btn1", "n_clicks"),
     Input("btn2", "n_clicks")
    ]
)
def render_table(data,b1,b2):
    print("Data: ", data)
    if data == None:
        return get_data().to_dict('records')
    
    df = pd.DataFrame(data)
    button_id = ctx.triggered[0]["prop_id"].split(".")[0]
    
    if button_id == 'btn1':
        df['test1'] += 1
    elif button_id == 'btn2':
        df['test2'] += 1
    return df.to_dict('records')

app.run_server()
1个回答

1
每次pathname触发第一个回调并将应用程序定向到主页面时,您的DataTable会被重置为代码开头定义的df。这就是为什么简单地设置表持久性不能帮助您,因为每次都要从零开始创建它。
如果您不想使用dcc.Store,您需要仅创建一次表格,并使用pathname触发来决定是否显示表格。这就是我在您的代码中所做的,我在主布局中定义了表格,在url不在主页面时,为表格父级div传递了一个{'display': 'none'}参数。
import pandas as pd
import numpy as np
from dash import Dash, callback, html, dcc, dash_table, Input, Output, dash_table, callback_context as ctx
import dash_bootstrap_components as dbc


df = pd.DataFrame({'test1':np.zeros(3), 'test2':np.zeros(3)})
def get_data():
    return df

app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions= True)
app.layout = dbc.Container([
    dcc.Location(id = 'url', refresh = False),
    dbc.Row(
        dbc.Navbar(
            dbc.Nav(children=[
                dbc.NavItem(dbc.NavLink("Main", active='exact', external_link=False, href='/'), id = 'main'),
                dbc.NavItem(dbc.NavLink("A link", active = 'exact', external_link=False, href="/link"), id = 'alink')
            ])
        )
    ),
    html.Div(id = 'link'),
    
    html.Div(id = 'table_div', children = [
            dbc.Row(
                dbc.Col([
                    dbc.Button("test1 +1", id='btn1', className="me-2", n_clicks = 0),
                    dbc.Button("test2 +1", id='btn2', className="me-2", n_clicks = 0)
                ])
            ),
            dbc.Row([
                dbc.Col(
                    dash_table.DataTable(columns = [{'name': x, 'id':x} for x in get_data().columns],
                                         id = 'table',
                                         persistence = True, 
                                         persisted_props = ['data'],
                                         persistence_type = 'session')
                )
            ])
    ])
])

@app.callback(
    Output('link', 'children'),
    Output('link', 'style'),
    Output('table_div', 'style'),
    Input('url', 'pathname')
)
def render_page(path):
    print(path)
    if path != '/':
        layout = html.Div(
            dbc.Row(
                html.H5(path)
            )
        )
        return layout, {'display': ''}, {'display': 'none'}
    else:
        # layout = main
        return [], {'display': 'none'}, {'display': ''}

@app.callback(
    Output('table', 'data'),
    [
     Input('table', 'data'),
     Input("btn1", "n_clicks"),
     Input("btn2", "n_clicks")
    ]
)
def render_table(data,b1,b2):
    print("Data: ", data)
    if data == None:
        return get_data().to_dict('records')
    
    df = pd.DataFrame(data)
    button_id = ctx.triggered[0]["prop_id"].split(".")[0]
    
    if button_id == 'btn1':
        df['test1'] += 1
    elif button_id == 'btn2':
        df['test2'] += 1
    return df.to_dict('records')

app.run_server()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接