Dash App 回调在数据框中附加新条目,如果与之前的任何条目匹配则替换

Dash App call back append new entry in data frame and replace if matches with any previous entry

我正在尝试构建一个破折号应用程序,该应用程序从用户那里获取输入并将每个条目附加到数据框中,但它会替换旧条目并生成新条目。我不确定回调中有什么问题。 如果用户条目与数据框的任何行匹配,则还尝试构建一个逻辑,那么只有它会替换其他追加。

非常感谢您的帮助:

@app.callback(Output('save-query', 'children'),
              [Input('save', 'n_clicks')],
              [State('ad_account_id', 'value'),
               State('app_id', 'value'),
               State('access_token', 'value'),
               State('app_secret', 'value'),
               State('metrics', 'value'),
               State('breakdown', 'value'),
               State('start-date', 'date'),
               State('end-date', 'date'),
               State('save-as', 'value')
               ],
              )
def save_query(clicks, ad_account_id, app_id, access_token, app_secret, metrics, breakdown,
               start_date, end_date, save):
    if clicks is not None:
        my_ad_account = ad_account_id
        my_app_id = app_id
        my_access_token = access_token
        my_app_secret = app_secret
        my_metrics = metrics
        my_breakdown = breakdown
        my_start_date = start_date
        my_end_date = end_date
        my_save = str.lower(save)
        data = [[my_save, my_ad_account, my_app_id, my_access_token, my_app_secret, my_metrics, my_breakdown,
                 my_start_date,
                 my_end_date]]
        df = pd.DataFrame(data, columns=['report_name', 'ad_account', 'app_id', 'access_token',
                                         'app_secret', 'metrics', 'breakdown',
                                         'start_date', 'end_date'])

        dff = df.append(df)

        return html.Div([
            dash_table.DataTable(
                css=[{'selector': '.row',
                      'rule': 'margin: 0; white-space: inherit; overflow: inherit; text-overflow: inherit;'}],
                id='table',
                columns=[{"name": i, "id": i} for i in dff.columns],
                data=dff.to_dict("rows"), )],
            style={'margin-top': 30, 'display': 'inline-block', 'margin-left': 20, 'width': '100%'})

由于全局变量的变化是 discouraged in Dash,允许访问当前数据的标准方法是添加一个将数据作为 State 参数保存的组件。它可以是一个单独的组件(例如 Store 组件)或只是数据 table 本身。这是一个演示后一种方法的小例子,

import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table
from dash.dependencies import Output, Input, State

user_key = 'access_token'
# Setup table.
columns = ['report_name', 'ad_account', 'app_id', 'access_token']
table = dash_table.DataTable(columns=[{"name": column, "id": column} for column in columns], data=[], id="table")
# Create app.
app = dash.Dash(prevent_initial_callbacks=True)
app.layout = html.Div([dcc.Input(id=column, value=column) for column in columns] +
                      [html.Button("Save", id="save"), dcc.Store(id="cache", data=[]), table])


@app.callback(Output("table", "data"), [Input("save", "n_clicks")], [State("table", "data")] +
              [State(column, "value") for column in columns])
def append(n_clicks, data, *args):
    record = {columns[i]: arg for i, arg in enumerate(list(args))}
    # If the record (identified by user_key) already exists, update it.
    try:
        record_index = [record[user_key] for record in data].index(record[user_key])
        data[record_index] = record
    # Otherwise, append it.
    except ValueError:
        data.append({columns[i]: arg for i, arg in enumerate(list(args))})
    # Return the updated data.
    return data


if __name__ == '__main__':
    app.run_server()

作为旁注,prevent_initial_callbacks 关键字是 Dash 1.12.0 的新关键字。顾名思义,它阻止了初始回调,从而消除了 if clicks is not None: 检查的需要。