Django传递数据库数据至D3.js折线图报错排查
问题修复方案
当前报错来自两处核心问题:
- 后端
pandas.to_json()默认输出列导向的嵌套对象,和D3折线图要求的行式对象数组结构不匹配 - 前端删除
d3.csv调用时残留了原方法的回调参数、多余逗号和闭合括号,存在JS语法错误,导致脚本直接终止运行,仅能渲染出Hello文本
第一步:修改后端视图的数据输出格式
调整pandas导出JSON的参数,直接输出D3可用的数组结构,同时重命名字段匹配绘图逻辑,修改后的views.py代码如下:
from django.shortcuts import render from cnxn import mysql_access import pandas as pd def homepage(request): sql = ''' select Date, Close from tbl_historical_prices where ticker = 'AAPL' ''' cnxn = mysql_access() conn = cnxn.connect() df = pd.read_sql(sql, con=conn) # 重命名字段匹配前端绘图逻辑,导出records格式的JSON df = df.rename(columns={"Date": "date", "Close": "value"}) context = {'AAPL': df.to_json(orient='records', date_unit='ms')} return render(request, 'index.html', context=context)
修改后模板渲染出的JSON结构为标准数组:[{"date":1641168000000,"value":182.01}, {"date":1641254400000,"value":179.7}],和官方示例CSV解析后的数据结构完全一致。
第二步:修复前端JS语法,替换数据源
删掉d3.csv残留的无效回调结构,直接读取渲染后的数据做格式化处理,再执行绘图逻辑,修改后的HTML代码如下:
{% load static %} <html> <script src="https://d3js.org/d3.v4.js"></script> <body> <h1> Hello! </h1> <div id="my_dataviz"></div> </body> <script> // 定义图表边距与尺寸 var margin = {top: 10, right: 30, bottom: 30, left: 60}, width = 460 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; // 挂载SVG画布 var svg = d3.select("#my_dataviz") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // 直接读取Django渲染的JSON数据 var rawData = {{ AAPL|safe }}; // 格式化数据:毫秒时间戳直接转Date对象,数值转数字类型 var data = rawData.map(function(d){ return { date : new Date(d.date), value : d.value } }); // 绘制X时间轴 var x = d3.scaleTime() .domain(d3.extent(data, function(d) { return d.date; })) .range([ 0, width ]); svg.append("g") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x)); // 绘制Y数值轴 var y = d3.scaleLinear() .domain([0, d3.max(data, function(d) { return +d.value; })]) .range([ height, 0 ]); svg.append("g") .call(d3.axisLeft(y)); // 绘制折线 svg.append("path") .datum(data) .attr("fill", "none") .attr("stroke", "steelblue") .attr("stroke-width", 1.5) .attr("d", d3.line() .x(function(d) { return x(d.date) }) .y(function(d) { return y(d.value) }) ) </script> </html>
验证说明
- 修改后页面源码中不存在多余的逗号、未闭合括号等语法问题,控制台无JS报错
- 折线图会正常渲染在id为
my_dataviz的容器内 - 如果日期显示异常,检查pandas读取数据库时是否正确将Date字段识别为时间类型即可
内容的提问来源于stack exchange,提问作者Lopez
相关产品推荐
相关产品推荐

