You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flask集成Plotly时图表渲染异常:数据与视觉展示不匹配/空白

Flask集成Plotly时图表渲染异常:数据与视觉展示不匹配/空白

看起来你遇到了Flask+Plotly集成里最头疼的一类问题——代码没报错、数据也对,但图表就是“不听话”。我之前排查过类似的情况,结合你的代码和已经做的尝试,给你整理几个针对性的修复方向,你可以按顺序试试:

一、先搞定序列化的核心问题

你已经试过fig.to_json()json.dumps(),但可能没注意到:直接序列化Figure实例有时候会带一些Plotly内部的元数据,干扰前端解析。建议你调整后端的序列化逻辑,优先用Plotly内置的序列化方法:

@app.route("/weather")
def weather():
    fig = go.Figure(data=go.Bar(x=["Mon", "Tue", "Wed"], y=[2, 5, 3]))
    # 优先用fig.to_json(),内部已经封装了正确的编码器,避免手动序列化的坑
    graphJSON = fig.to_json()
    # 备选方案:转成字典再序列化,过滤掉Figure实例的额外元数据
    # graphJSON = json.dumps(fig.to_dict(), cls=plotly.utils.PlotlyJSONEncoder)
    return render_template("weather.html", graphJSON=graphJSON)

二、前端渲染的两个关键检查

1. 先确认前端拿到的是正确数据

无报错的情况下,首先要在浏览器控制台验证数据是否正确传递。修改前端代码,加入打印:

<div id="plot"></div>
<script>
    var graph = {{ graphJSON | safe }};
    // 打印数据到控制台,检查x、y值是不是和后端完全一致
    console.log("实际拿到的图表数据:", graph.data[0].x, graph.data[0].y);
    Plotly.newPlot("plot", graph.data, graph.layout);
</script>

打开浏览器F12的控制台,看看打印出来的x是不是["Mon", "Tue", "Wed"],y是不是[2,5,3]——如果这里的数据就不对,那问题出在Jinja渲染或者序列化环节。

2. 尝试直接传入完整的graph对象

Plotly的newPlot方法其实支持直接传入完整的Figure序列化对象,不需要拆分datalayout,有时候拆分反而会漏掉一些隐藏的配置:

// 替换原来的渲染代码,直接传整个graph对象
Plotly.newPlot("plot", graph);

三、必做:对齐前后端Plotly版本

这是很多人忽略的点——如果后端用的是Plotly 5.x,前端CDN却用了4.x(或者反过来),序列化的JSON结构会不兼容,导致图表渲染异常。

  • 后端执行print(plotly.__version__)查看版本
  • 前端CDN改成对应版本,比如后端是5.15.0,就用:
<script src="https://cdn.plot.ly/plotly-5.15.0.min.js"></script>

四、最后检查Jinja渲染的JSON结构

打开页面的“查看源代码”,找到var graph = ...这一行,看看生成的JSON是不是完全正确:

  • 所有引号应该是双引号,没有被转义成&quot;
  • 数组结构完整,比如x":["Mon","Tue","Wed"]而不是x:"Mon,Tue,Wed"
    如果这里有问题,可能是Jinja的安全过滤器没生效,你可以试试{{ graphJSON | tojson | safe }}(不过你已经用了| safe,大概率是序列化的问题)

完整修正后的示例代码

后端(Flask)

import plotly.graph_objs as go
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/weather")
def weather():
    # 确保数据是Python原生列表(避免numpy/pandas类型的隐性问题)
    x_days = ["Mon", "Tue", "Wed"]
    y_temps = [2, 5, 3]
    fig = go.Figure(data=go.Bar(x=x_days, y=y_temps))
    # 优先使用内置的to_json方法
    graphJSON = fig.to_json()
    return render_template("weather.html", graphJSON=graphJSON)

if __name__ == "__main__":
    app.run(debug=True)

前端(HTML/Jinja)

<!DOCTYPE html>
<html>
<head>
    <title>Weather Plot</title>
</head>
<body>
    <div id="plot" style="width: 600px; height: 400px;"></div>
    <!-- 用和后端版本一致的Plotly CDN -->
    <script src="https://cdn.plot.ly/plotly-5.15.0.min.js"></script>
    <script>
        var graph = {{ graphJSON | safe }};
        // 先验证数据
        console.log("验证数据:", graph.data[0].x, graph.data[0].y);
        // 直接传入完整graph对象渲染
        Plotly.newPlot("plot", graph);
    </script>
</body>
</html>

按照这个顺序排查,应该能定位到问题——大概率是序列化方式或者版本不兼容的问题。

内容来源于stack exchange

火山引擎 最新活动