您好,我是第一次使用破折号应用程序,无法修复 我面临的一个问题。我有一个前端,需要用户输入,进行一些计算,将结果存储在隐藏的div中,然后更新图形。
该应用程序加载正常,但是一旦我按下“提交”按钮,它就会出错。以下是我编写的代码。看起来两个回调函数都同时触发。
app.layout = html.Div(style={'backgroundColor': colors['background']}, children=[
html.Div([
html.Div([
html.Img(src='data:image/png;base64,{}'.format(encoded_image.decode()), className="nine columns")
], className="three columns"),
html.Div([
html.Div([
html.Div([
html.P("Select Month Range:"),
],
className="two columns"
),
html.Div([
dcc.RangeSlider(
id='month_slider',
# updatemode='drag',
# count=1,
min=1,
max=maxmarks,
step=1,
value=[maxmarks - 1, maxmarks],
marks=tags,
pushable=1
),
],
className="six columns",
style={})
],
className="twelve columns",
style={
'backgroundColor': '#EFEAEA',
'padding-top': '1.5em',
'padding-bottom': '1em'
}),
html.Div([
html.Div([
dcc.Dropdown(
id='demographics',
options=[
{'label': 'All 18-49', 'value': '18-49'},
{'label': 'Female 25-54', 'value': '25-54F'},
{'label': 'All 25-54', 'value': '25-54'},
],
placeholder="Select Demographics",
)
],
className="two columns",
style={}),
html.Div([
dcc.Dropdown(
id='ID',
options=[
{'label': '200', 'value': 200, 'type': 'number'},
{'label': '250', 'value': 250, 'type': 'number'},
{'label': '300', 'value': 300, 'type': 'number'},
{'label': '350', 'value': 350, 'type': 'number'},
{'label': '400', 'value': 400, 'type': 'number'},
],
placeholder="Select ID",
)
],
className="two columns",
style={}),
html.Div([
dcc.Dropdown(
id='Income',
options=[
{'label': '50,000', 'value': 50000, 'type': 'number'},
{'label': '100,000', 'value': 100000, 'type': 'number'},
{'label': '200,000', 'value': 200000, 'type': 'number'},
{'label': '350,000', 'value': 350000, 'type': 'number'},
{'label': '500,000', 'value': 500000, 'type': 'number'},
],
placeholder="Select Income",
)
],
className="two columns",
style={}),
html.Div([
dcc.Dropdown(
id='Frquency',
options=[
{'label': 'None per week, 'value': 0, 'type': 'number'},
{'label': 'Once per Week', 'value': 1, 'type': 'number'},
{'label': 'Thrice per Week', 'value': 3, 'type': 'number'},
],
placeholder="Select Frequency",
)
],
className="two columns",
style={}),
html.Div([
html.Button('Submit', id='submit_button', className='twelve columns',
style={'background-color': '#2D91C3', 'color': 'white', 'font-size': '1em'})
],
className="two columns",
style={}),
],
className="twelve columns",
style={
'backgroundColor': '#EFEAEA',
'padding-top': '1em',
'padding-bottom': '1.5em'
})
], className="nine columns", style={})
], className="twelve columns"),
# dcc.graph layout
html.Div([
html.Div([
dcc.Graph(id='example-graph', config={"displayModeBar": False, "scrollZoom": False})
],
className="six columns",
style={'border-right': 'thin grey solid', 'border-left': 'thin grey solid',
'border-top': 'thin grey solid'}),
html.Div(id='intermediate-value1', style={'display': 'none'})
])]
@app.callback(
Output("intermediate-value1", "children"),
[Input("submit_button", "n_clicks")],
[
State("month_slider", "value"),
State("demographics", "value"),
State("Income", "value"),
State("Frequency", "value"),
],
)
def clean_data(n_clicks, month_range, demo, inc, fre_cap):
if n_clicks is not None and n_clicks > 0:
employee_data_temp = employee_data.copy()
start_date = month_range[0]
end_date = month_range[1]
mask1 = employee_data_temp["total_months"] == int(end_date - start_date)
employee_data_temp = employee_data_temp.loc[mask1]
mask2 = (
(employee_data_temp["demographic"] == demo)
& (employee_data_temp["freq_cap"] == fre_cap)
& (employee_data_temp["total_incressions"] == inc)
)
employee_data_temp = employee_data_temp.loc[mask2]
employee_data_temp = employee_data_temp.sort_values(by=["reach"])
employee_data_temp["income_percent"] = (employee_data_temp["reach"] / 955000) * 100
employee_data_temp = employee_data_temp.reset_index(drop=True)
return employee_data_temp.to_json(date_format="iso", orient="split")
else:
return []
@app.callback(Output("example-graph", "figure"),
[Input("submit_button", "n_clicks")],
[State("intermediate-value1", "children"),
State("Income", "value")])
def update_graph(n_clicks, employee_data_temp, inc):
t.sleep(2)
if n_clicks is not None and n_clicks > 0:
dff = pd.read_json(employee_data_temp, orient="split")
max_income = dff["income_percent"].iloc[9]
max_income = max_income.round(2)
trace = Scatter(
y=dff["income_percent"], x=dff["inc"], line=plotly.graph_objs.scatter.Line(color="#1a2d46"), mode="lines"
)
layout1 = Layout(
plot_bgcolor="#FFFFFF",
paper_bgcolor="#FFFFFF",
height=450,
title="Digital Reach - " + str(max_income) + " " + "%",
xaxis=dict(showgrid=True, showline=True, zeroline=True, fixedrange=True, title="Total Income"),
yaxis=dict(showline=True, fixedrange=True, zeroline=True, title="Income (%)"),
margin=plotly.graph_objs.layout.Margin(t=45, l=50, r=50),
)
return Figure(data=[trace], layout=layout1)
else:
return []
以下是我得到的错误:
Traceback (most recent call last):
File "C:\Users\Tushar\Documents\django_projects\tvnz_dash_app\src\dash_app\incrementor\views.py", line 21, in dispatcher
response = server.full_dispatch_request()
File "C:\python37\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\python37\lib\site-packages\flask\app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\python37\lib\site-packages\flask\_compat.py", line 35, in reraise
raise value
File "C:\python37\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "C:\python37\lib\site-packages\flask\app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\python37\lib\site-packages\dash\dash.py", line 1073, in dispatch
response.set_data(self.callback_map[output]['callback'](*args))
File "C:\python37\lib\site-packages\dash\dash.py", line 969, in add_context
output_value = func(*args, **kwargs)
File "C:\Users\Tushar\Documents\django_projects\tvnz_dash_app\src\dash_app\incrementor\router.py", line 699, in update_graph
dff = pd.read_json(employee_data_temp, orient="split")
File "C:\python37\lib\site-packages\pandas\io\json\json.py", line 413, in read_json
path_or_buf, encoding=encoding, compression=compression,
File "C:\python37\lib\site-packages\pandas\io\common.py", line 232, in get_filepath_or_buffer
raise ValueError(msg.format(_type=type(filepath_or_buffer)))
ValueError: Invalid file path or buffer object type: <class 'NoneType'>
我想要的是该功能应该在用户单击提交按钮时运行,并且由于更新图功能取决于清洁数据功能,因此除非以及直到清洁数据功能完成,否则该功能才应运行。
请有人帮我弄清楚我在这里想念什么,并帮助解决问题。
非常感谢!
新的更新功能
@app.callback(
Output("intermediate-value1", "children"),
[Input("submit_button", "n_clicks")],
[
State("month_slider", "value"),
State("demographics", "value"),
State("digital_impressions", "value"),
State("digital_frequency", "value"),
],
)
def get_match(n_clicks, month_range, demo, tarps):
if n_clicks is not None and n_clicks > 0:
some long python script data calculatation
return match_data_temp.to_json(date_format="iso", orient="split")
@app.callback(
Output("intermediate-value2", "children"),
[Input("submit_button", "n_clicks")],
[
State("month_slider", "value"),
State("demographics", "value"),
State("digital_impressions", "value"),
State("digital_frequency", "value"),
],
)
def clean_data(n_clicks, month_range, demo, inc, fre_cap):
if n_clicks is not None and n_clicks > 0:
employee_data_temp = employee_data.copy()
start_date = month_range[0]
end_date = month_range[1]
mask1 = employee_data_temp["total_months"] == int(end_date - start_date)
employee_data_temp = employee_data_temp.loc[mask1]
mask2 = (
(employee_data_temp["demographic"] == demo)
& (employee_data_temp["freq_cap"] == fre_cap)
& (employee_data_temp["total_incressions"] == inc)
)
employee_data_temp = employee_data_temp.loc[mask2]
employee_data_temp = employee_data_temp.sort_values(by=["reach"])
employee_data_temp["income_percent"] = (employee_data_temp["reach"] / 955000) * 100
employee_data_temp = employee_data_temp.reset_index(drop=True)
return employee_data_temp.to_json(date_format="iso", orient="split")
@app.callback(
Output("intermediate-value3", "children"),
[
Input("month_slider", "value"),
Input("demographics", "value"),
Input("intermediate-value2", "children"),
Input("intermediate-value1", "children"),
],
)
def get_match_overlap(month_range, demo, match_data_temp, employee_data_temp):
overlap_match = pd.read_json(match_data_temp, orient="split")
overlap_employee = pd.read_json(employee_data_temp, orient="split")
some long python calculatation
return final.to_json(date_format="iso", orient="split")
@app.callback(
Output("example-graph2", "figure"),
[Input("intermediate-value3", "children"), Input("intermediate-value2", "children")],
)
def update_graph(final, match_data_temp):
if final is not None:
dff_overlap = pd.read_json(final, orient="split")
dff_match_data = pd.read_json(match_data_temp, orient="split")
overlap = Scatter(
y=dff_overlap["final"],
x=dff_overlap["percentage"],
name="tile",
line=plotly.graph_objs.scatter.Line(color="red"),
mode="lines",
)
layout1 = Layout(
plot_bgcolor="#FFFFFF",
paper_bgcolor="#FFFFFF",
title="title",
height=550,
xaxis=dict(showgrid=True, showline=True, zeroline=False, fixedrange=True, title="% Campaign Completion", range=[0, 100]),
yaxis=dict(showline=True, fixedrange=True, zeroline=False, title="Audience Reached (%)", range=[0, (reach_increment + 10)]),
margin=plotly.graph_objs.layout.Margin(t=45, l=50, r=50),
)
linear = Scatter(
y=dff_match_data["Final"],
x=dff_match_data["percentage"],
name="title",
line=plotly.graph_objs.scatter.Line(color="black"),
mode="lines",
)
return Figure(data=[overlap, linear], layout=layout1)
@app.callback(Output("example-graph", "figure"),
[Input("submit_button", "n_clicks")],
[State("intermediate-value2", "children"),
State("Income", "value")])
def update_graph(n_clicks, employee_data_temp, inc):
if employee_data_temp is not None:
dff = pd.read_json(employee_data_temp, orient="split")
trace = Scatter(
y=dff["income_percent"], x=dff["inc"], line=plotly.graph_objs.scatter.Line(color="#1a2d46"), mode="lines"
)
layout1 = Layout(
plot_bgcolor="#FFFFFF",
paper_bgcolor="#FFFFFF",
height=450,
title="Digital - " + str(max_income) + " " + "%",
xaxis=dict(showgrid=True, showline=True, zeroline=True, fixedrange=True, title="Total Income"),
yaxis=dict(showline=True, fixedrange=True, zeroline=True, title="Income (%)"),
margin=plotly.graph_objs.layout.Margin(t=45, l=50, r=50),
)
return Figure(data=[trace], layout=layout1)
答案 0 :(得分:2)
好的,首先要注意一些小事情。这里有一些语法错误,尽管它们可能不在原始文件中。您的ID丢失,因为id='Frequency',
有错字。轻松修复。我收到了许多关于Dropdown
道具不正确的警告,我通过删除为每个下拉选项传递的type='number'
解决了这个问题。我还将update_graph
的默认返回值更改为一个空字典,这解决了另一个类型错误。
现在需要更大的东西。您正在使用同一按钮触发两个回调。第一个处理数据,并将其存储在隐藏的div中。第二个睡眠足够长的时间以允许第一个睡眠,然后在隐藏的div中运行。问题在于,第二个回调函数将在其运行后立即拉入该隐藏div的内容,并且它休眠的事实不会更改它与一起使用的值,即使该值在睡眠计时器结束。
此处的解决方法是合并回调。您可以删除隐藏的div,只需在单个回调中完成所有工作即可开始。