我想在导航.py中点击导航时在导航的下面打开app.py, 但打开app.py会数据不加载,点日期控件也不触发app.py里的回调来更新数
我写了一个可以独立运行的app.py,思路是这样:
第一步:创建 日期控件、空的表格、空的柱状图,
# 创建时间范围控件
date_picker = dcc.DatePickerRange(
id='date-picker',
min_date_allowed=pd.to_datetime('2023-01-01'), # 最小可选时间
max_date_allowed=pd.to_datetime('today') , # 最大选时间 截止到今天
start_date = ( pd.to_datetime('today')-pd.DateOffset(days=15) ).strftime('%Y-%m-%d'), # 默认开始时间 : 前 7 天
end_date=( pd.to_datetime('today')-pd.DateOffset(days=1) ).strftime('%Y-%m-%d')# 默认结束时间:前一天
)
# 创建时间 单选控件
Year_picker = dcc.DatePickerSingle(
id='Year-picker',
display_format='YYYY',
date='2023'
)
## 创建日期控件
date_picker2 = dcc.DatePickerSingle(
id='date-picker-2',
placeholder='预算的月份', # 未选择日期输入框中默认文本
#title='Click to select date',
display_format='YYYYMM', # 选中期后的显示格式。
date=datetime.today().strftime('%Y-%m-%d'),
#style={'display': 'inline-block', 'marginRight': '10px','font-size': '10px','position': 'sticky', 'top': '0', 'zIndex': '1'},
)
# 创建一个绘图:来放趋势图
trend_chart = dcc.Graph(id='trend-graph')
# 创建堆积条形图
Stack_chart = dcc.Graph(id='stacked-bar-chart')
第二步:然后在app.layout里加载
# 创建页面布局
app.layout = html.Div([
html.H1('DSP预算比变化'),
html.Br(),
html.Br(),
dbc.Container([
dbc.Row([
dbc.Col(html.H1('每月预算')),
dbc.Col(html.H1('预算变化趋势')),
]),
dbc.Row([
dbc.Col([
Year_picker, # 控制 预算年
date_picker2, # 控制 预算 月
date_picker, # 控制 预算 备份的 时间范围
])
]),
dbc.Row([
dbc.Col(
Stack_chart, #条形图
width=6
),
dbc.Col(
trend_chart, #趋势图
width=6
),
]),
dbc.Row([
dbc.Col([
html.H3("预算变化明细"),
data_table, #数据明细表
#fac_table,
])
])
],fluid=True),
])
app_layout=app.layout
第三步: 在回调中操作数据库和监听日期控件来更新表格和柱状图的数据。 到这里单独运行app.py都没问题
# 回调函数:每月预算 -条形例图
@app.callback(
Output('stacked-bar-chart','figure'),
Input('Year-picker', 'date')
)
def update_dar_char(date):
# 从连接池获取连接
connection = pool.connection()
# 查询SQL数据
date_str = datetime.strptime(date, '%Y').strftime('%Y')+'00' # start_date 传过来的是 字符格式,先转换成 原生一样的时间格式, 然后再转换格式
query = f''' select '''
df = pd.read_sql_query(query,connection)
# 计算每月的 总计
group_totals = df.groupby('YearMonth')['Budget_USD'].sum().reset_index()
connection.close()
# 创建 柱状图
fig = px.bar(
df,
x=df['YearMonth'],
y=df['Budget_USD'],
color=df['代理商'],
color_discrete_map= {'SparkX':'#cc00ff','Xtream':'#ff6633'}, # 设置 分组的颜色
text_auto= True , # 数据标签
)
fig.update_xaxes(type='category',tickangle=45) # 将X轴标签格式化为分类数据,而不是数值数据,避免以科学数值格式显示
return fig
# 回调函数,3-预算变化明细表格- 更新DataTable的数据
@app.callback(
Output('data-table', 'data'), # 这里如果要换成 Dash 的 Datatable 直接改表格id 值 data-table-fac 改成 data-table
Output('data-table', 'columns'),
[Input('date-picker-2', 'date'),
Input('date-picker', 'start_date'),
Input('date-picker', 'end_date')]
)
def update_data_table(date,date_A,date_B):
# 将日期对象转换为字符串格式
#### 这里 要加一个 空 值 判断
date_str = datetime.strptime(date, '%Y-%m-%d').strftime('%Y%m') #先把转入的 date 转换成跟上面一样的格式, 再用Strftime 转换成 想要的格式
date_A = datetime.strptime(date_A, '%Y-%m-%d').strftime('%m%d')
date_B = datetime.strptime(date_B, '%Y-%m-%d').strftime('%m%d')
# 从连接池获取连接
connection = pool.connection()
sql =f''' select '''
df = pd.read_sql_query(sql,connection)
# 指定'列名1'列的数据类型为浮点型
df['advertiserId'] = df['advertiserId'].astype(str)
df['上次预算'] = df['上次预算'].map('{:,.0f}'.format)
df['最近预算'] = df['最近预算'].map('{:,.0f}'.format)
# 关闭数据库连接
connection.close()
# 将DataFrame转换为字典列表
data = df.to_dict('records')
return data,columns
问题来了:
单独运行app.py都没问题,但在用Dash导航py加载app.py里,只加上了app.layout的布局,回调里的没运行,点日期也没反应。
# 在导航布局py中加载app.py
# 回调函数来根据 URL 路径切换页面内容或打开外部网页
@app.callback(
Output('page-content', 'children'),
Input('url', 'pathname')
)
def display_page(pathname):
if pathname == '/about':
return line.app_layout
elif pathname == '/services':
return None
elif pathname == '/contact':
return html.Iframe(src='/', width="100%", height="800px")
elif pathname == '/trend':
return None
else:
return html.Div("Welcome to the Home Page!", id="home")