Dash上线子路径需设requests_pathname_prefix='/bi/',Nginx配置proxy_pass末尾斜杠不可少;图表更新须返回新figure对象而非修改原data;多输入触发应查callback_context.triggered;用户数据须存dcc.Store,禁用全局变量。

Dash 的 dash.Dash 实例必须显式传入 requests_pathname_prefix 才能部署到子路径
本地开发时直接访问 http://localhost:8050 没问题,但上线到 Nginx 或 Apache 的子路径(比如 /bi/)时,Dash 会加载错位的 JS/CSS 资源,页面白屏或报 404。根本原因是 Dash 默认按根路径生成静态资源 URL。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 启动应用时明确设置
requests_pathname_prefix='/bi/'(末尾斜杠不能少) - Nginx 配置里用
location /bi/ { proxy_pass http://127.0.0.1:8050/; },注意proxy_pass后的结尾斜杠——它决定是否剥离前缀 - 别依赖
get_relative_path()自动推导:它只在回调中可用,初始 HTML 加载阶段不生效
Plotly 图表更新必须走 dash.Output + dash.Input,不能直接改 fig.data
常见错误是把 Dash 当成 Jupyter:在回调里拿到 fig = px.line(...) 后,直接 fig.data[0].x = new_x,结果界面不动。Dash 不监听 Plotly 对象内部属性变化,只认整个 figure 字典的替换。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 每次更新都返回一个全新
dict或go.Figure实例,例如return px.scatter(df, x='a', y='b').to_dict() - 避免在回调里复用
px返回的 figure 对象,尤其不要缓存后反复修改.update_traces() - 大数据量时用
Figure.to_plotly_json()替代.to_dict(),减少序列化开销
dash.callback_context.triggered 是判断多输入触发源的唯一可靠方式
BI 后台常有多个下拉框、日期选择器共用一个图表回调,需要知道“这次是谁动的”。有人用 if a is not None 判断,但空字符串、0、[] 都可能被误判为“未触发”;也有人靠默认值兜底,结果默认值一变逻辑就崩。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 回调开头立刻读
ctx = dash.callback_context,检查ctx.triggered是否为空列表(首次加载时为空) - 取
ctx.triggered[0]['prop_id'],它形如"date-picker.range.value"或"country-dropdown.value",可直接做字符串匹配 - 别依赖
dash.no_update返回来跳过更新——它只是跳过输出,仍会执行回调体,可能引发副作用
服务器端状态不能存在全局变量里,得用 dash.dcc.Store 或后端缓存
写 BI 后台时容易随手定义 global_df = pd.read_csv(...),本地调试正常,上线后多用户并发访问,数据互相污染,图表显示错乱。Python 进程模型决定了全局变量是进程级共享的,不是用户级隔离的。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用户专属数据(如上传的 CSV、筛选后的子集)必须存在
dcc.Store组件里,通过state输入进回调 - 高频读取的公共数据(如维度字典、基础指标口径)可用
functools.lru_cache缓存,但注意缓存键要包含版本号或更新时间戳 - 绝对不要在回调外做耗时 IO(比如每次回调都
pd.read_sql),它会阻塞整个 Dash 进程










