【问题标题】:How can we create data columns in Dash Table dynamically using callback with a function providing the dataframe我们如何通过提供数据框的函数使用回调在 Dash Table 中动态创建数据列
【发布时间】:2019-04-22 22:15:18
【问题描述】:

我正在尝试使用 Inputs 在 Web 上创建破折号表。但是问题是数据是从回调和先验的数据库中创建的, 除非使用回调函数创建熊猫数据框,否则我不知道列的名称。 我已经检查过我得到了正确的数据。但是无法显示它。我使用了多个输出选项(使用 Dash 0.41)

我的代码如下:(我没有提供在回调 someFunc 中生成 pandas 数据帧的函数的详细信息, 因为这对于这个 Dash 代码故障排除的目的并不重要。

 import dash_table as dt

 def someFunc(ID, pattern_desc, file_path):

       ## do something 
      return df # pandas dataframe
#
 external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

 app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

 server = app.server

 app = dash.Dash(__name__)

 app.config.suppress_callback_exceptions = True
 app.css.config.serve_locally = True
 app.scripts.config.serve_locally = True


 app.layout = html.Div(
      children = [
      html.Div(
      id = 'title',
      children = appTitle,
      className = 'titleDiv'  
   ),
 html.Div(
    children = [
        html.Div(
            children = "Enter ID:",
            className = 'textDiv'
        ),
        dcc.Input(
            id = 'ID',
            type = 'text',
            value = 'ABCER1',
            size = 8),

        html.Div(
            children = "Enter Test Pattern",
            className = 'textDiv'
        ),
        dcc.Input(
            id = 'pattern_desc',
            type = 'text',
            value = 'Sample',
            size = 20),

         html.Div(
            children = "Enter File OutPut Path:",
            className = 'textDiv'
        ),
        dcc.Input(
            id = 'file_path',
            type = 'text',
            value = '',
            size = 30),

        html.Button(
            id = 'submit',
            n_clicks = 0,
            children = 'Search'
        )
    ]
),

    html.Div(
        id = 'tableDiv',
        children = dash_table.DataTable(
        id = 'table',
        style_table={'overflowX': 'scroll'},
        style_as_list_view=True,
        style_header={'backgroundColor': 'white','fontWeight': 
            'bold'},
         ),
        className = 'tableDiv'
    )
  ]
)

  # callback to update the table
  @app.callback([Output('table', 'data'),Output('table', 'columns')]
          [Input('submit', 'n_clicks')],
          [State('ID', 'value'),  State('pattern_desc', 'value'), 
        State('file_path', 'value')])
   def update_table(n_clicks, ID, pattern_desc, file_path):

         df = someFunc(ID, pattern_desc, file_path)
    mycolumns = [{'name': i, 'id': i} for i in df.columns]
        return html.Div([
                dt.DataTable(
            id='table',
            columns=mycolumns,
            data=df.to_dict("rows")
         )
        ])

因此,在这种情况下,接受 3 个输入参数的函数 someFunc 返回一个 pandas 数据帧,该数据帧可以根据输入具有不同的列。因此应用程序布局应该显示 回调函数的输出根据输入动态给出的那些列。 我应该让网页填充表格和列,但是却出现错误。当我运行它时,我将通过函数生成的数据获取到文件中,但破折号无法 在网页上生成表格。我收到以下错误:

dash.exceptions.InvalidCallbackReturnValue:回调 ..table.data...table.columns.. 是一个多输出。 期望输出类型是列表或元组,但得到 Div([DataTable(columns=[{'name': 'pattern_desc', 'id': 'pattern_desc'}, ......

不确定我该如何实现。任何帮助将不胜感激。

【问题讨论】:

    标签: python html css pandas plotly-dash


    【解决方案1】:

    在您的 Dash 回调中,您应该向 2 个单独的输出返回 2 个单独的值: [Output('table', 'data'),Output('table', 'columns')]

    你要回来了:

    return html.Div([
                    dt.DataTable(
                id='table',
                columns=mycolumns,
                data=df.to_dict("rows")
             )
            ])
    

    只有 1 个输出。

    Dash 期望在一个列表或一个像这样的元组中有 2 个返回值:

    return("output1" , outputVariable2)
    

    或

    return[ Html.Div("text") , "output Text 2"]
    

    为了解决这个问题,要么在一个元组或列表中返回 2 个值,要么编辑您的输出要求,以便只需要一个值。

    从外观上看,您正试图返回一个包含 Datatable 的 Div,因此您可以进行以下更改:

        html.Div(
            id = 'tableDiv',
            className = 'tableDiv'
        )
    
    ...
    
      @app.callback([Output('tableDiv', 'children')]
              [Input('submit', 'n_clicks')],
              [State('ID', 'value'),  State('pattern_desc', 'value'), 
            State('file_path', 'value')])
       def update_table(n_clicks, ID, pattern_desc, file_path):
    
             df = someFunc(ID, pattern_desc, file_path)
        mycolumns = [{'name': i, 'id': i} for i in df.columns]
            return html.Div([
                    dt.DataTable(
                id='table',
                columns=mycolumns,
                data=df.to_dict("rows")
             )
            ])
    

    【讨论】:

    • 谢谢迈克。我会尝试代码并及时通知您。
    • Mked,我尝试了这两个版本,通过保持我的代码完整并返回一个元组以及您粘贴为 TableDiv 的修改后的代码,孩子们。没有任何效果。唯一的问题是,这一次,我没有收到任何错误,并且还生成了输出文件(它是在调用 somefunc 函数时创建的),但是在点击提交按钮时,页面关闭并且没有显示表格。
    • 这意味着您询问的错误已修复。您的代码中一定还有其他问题。您应该考虑将此问题标记为已解决并提出不同的问题。
    • 谢谢我已经能够修复它。感谢您的帮助
    【解决方案2】:

    如果我对您的理解正确,那么您可以简单地创建另一个回调来输出 columns 属性的更新值。您还可以使用多输出回调同时更新两者。

    @app.callback(Output('table', 'columns'),
        [Input('submit', 'n_clicks')],
        [State('ID', 'value'),  State('pattern_desc', 'value'), 
         State('file_path', 'value')])
    def update_table(n_clicks, ID, pattern_desc, file_path):
        mydata = someFunc(ID, pattern_desc, file_path)
        # here you would use the dataframe columns to create the new column values
        return new_column_values
    

    【讨论】:

    • 谢谢珊瑚。我使用了类似的东西,但仍然无法正常工作。我是否需要在我定义表格的布局中放置任何内容:
    • def update_table(n_clicks, ID, pattern_desc, file_path): mydata = someFunc(ID, pattern_desc, file_path) mydata2 = mydata.to_dict("rows") mycols = [{'name': i, 'id': i} for i in mydata.columns] return mycols, mydata2
    • 新回调在装饰器中的输出列表后没有逗号。运行应用程序时是否遇到任何错误?
    • 这是一个错字,实际代码中没有。当我运行程序时,我得到了当前表单中的错误。
    • 好的,是的。我看到您的输出包含在 div 中,但您应该看起来像这样:return df.to_dict("rows"), mycolumns
    猜你喜欢
    • 1970-01-01
    • 2018-10-02
    • 2023-02-26
    • 2021-09-16
    • 2020-08-17
    • 2020-03-18
    • 2018-05-15
    • 1970-01-01
    • 2012-11-14
    相关资源
    最近更新 更多