我目前正在尝试使用Pandas在Flask中编写CSV文件,然后应由D3.js读取。但是,没有生成CSV文件,我收到错误http://127.0.0.1:5000/test.csv 500 (INTERNAL SERVER ERROR)
和Uncaught ProgressEvent
,这是由于找不到CSV文件所致。
我尝试了不同的解决方案,即尝试使用dataframe.to_csv(path)
编写CSV,但是文件从未生成并且没有错误返回。
我还尝试使用缓冲区和Flask的内置send_file
方法创建一个临时的CSV文件,以供d3.csv(...)
读取。但是,该文件似乎从未生成过,并且在浏览器控制台中出现了上述http://127.0.0.1:5000/test.csv 500 (INTERNAL SERVER ERROR)
和Uncaught ProgressEvent
错误。以下是我当前代码的摘要。
Python
def get_d3_data(doc_id):
...
buffer = StringIO()
dataframe.to_csv(buffer, encoding='utf-8')
buffer.seek(0)
return send_file(buffer,
attachment_filename="test.csv",
mimetype='text/csv')
def rank(doc_id):
...
get_d3_data(doc_id)
return render_template('rank.html', ...)
JavaScript
以下https://gist.github.com/mbostock/6fead6d1378d6df5ae77bb6a719afcb2
中的代码...
d3.csv("test.csv", function(d, i, columns) {
for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
d.total = t;
return d;
}, function(error, data) {
if (error) throw error;
x.domain(data.map(function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
z.domain(data.columns.slice(1));
g.append("g")
.selectAll("g")
.data(d3.stack().keys(data.columns.slice(1))(data))
.enter().append("g")
.attr("fill", function(d) { return z(d.key); })
.selectAll("path")
.data(function(d) { return d; })
.enter().append("path")
.attr("d", d3.arc()
.innerRadius(function(d) { return y(d[0]); })
.outerRadius(function(d) { return y(d[1]); })
.startAngle(function(d) { return x(d.data.date); })
.endAngle(function(d) { return x(d.data.date) + x.bandwidth(); })
.padAngle(0.01)
.padRadius(innerRadius));
var label = g.append("g")
.selectAll("g")
.data(data)
.enter().append("g")
.attr("text-anchor", "middle")
.attr("transform", function(d) { return "rotate(" + ((x(d.date) + x.bandwidth() / 2) * 180 / Math.PI - 90) + ")translate(" + innerRadius + ",0)"; });
label.append("line")
.attr("x2", -5)
.attr("stroke", "#000");
label.append("text")
.attr("transform", function(d) { return (x(d.date) + x.bandwidth() / 2 + Math.PI / 2) % (2 * Math.PI) < Math.PI ? "rotate(90)translate(0,16)" : "rotate(-90)translate(0,-9)"; })
.text(function(d) { return d.date; });
var yAxis = g.append("g")
.attr("text-anchor", "middle");
var yTick = yAxis
.selectAll("g")
.data(y.ticks(5).slice(1))
.enter().append("g");
yTick.append("circle")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("r", y);
yTick.append("text")
.attr("y", function(d) { return -y(d); })
.attr("dy", "0.35em")
.attr("fill", "none")
.attr("stroke", "#fff")
.attr("stroke-width", 5)
.text(y.tickFormat(5, "s"));
yTick.append("text")
.attr("y", function(d) { return -y(d); })
.attr("dy", "0.35em")
.text(y.tickFormat(5, "s"));
yAxis.append("text")
.attr("y", function(d) { return -y(y.ticks(5).pop()); })
.attr("dy", "-1em")
.text("Population");
var legend = g.append("g")
.selectAll("g")
.data(data.columns.slice(1).reverse())
.enter().append("g")
.attr("transform", function(d, i) { return "translate(-40," + (i - (data.columns.length - 1) / 2) * 20 + ")"; });
legend.append("rect")
.attr("width", 18)
.attr("height", 18)
.attr("fill", z);
legend.append("text")
.attr("x", 24)
.attr("y", 9)
.attr("dy", "0.35em")
.text(function(d) { return d; });
});
...
我还尝试将CSV数据作为字符串传输到Javascript代码,并尝试使用d3.csvParse(...)
读取数据(有效)。但是,我尚未将d3.csv(...)
代码转换为有效的d3.csvParse(...)
代码。
我应该从var rankingscsv= '{{ rankingscsv|tojson|safe }}';
获得的CSV
"date,fours,fives,sixes,sevens,eights,nines
2019-01-01,0,0,0,0,0,0
2019-01-02,3,0,0,0,0,0
2019-01-03,0,0,0,0,0,0
2019-01-04,0,0,0,0,0,0
2019-01-05,0,0,0,0,0,0
2019-01-06,0,1,0,0,0,0
2019-01-07,1,0,0,0,0,0
2019-01-08,0,0,0,0,0,0
2019-01-09,0,0,0,0,0,0
2019-01-10,1,0,0,0,0,0
2019-01-11,0,0,0,0,0,0
2019-01-12,0,2,0,0,0,0
2019-01-13,2,0,1,0,0,0
2019-01-14,2,1,0,0,0,0
2019-01-15,0,0,0,0,0,0
2019-01-16,2,0,0,0,0,0
2019-01-17,2,0,0,0,0,0
2019-01-18,3,0,0,0,0,0
2019-01-19,0,0,0,0,0,0
2019-01-20,2,0,0,0,0,0
2019-01-21,0,0,0,0,0,0
2019-01-22,0,0,1,0,0,0
2019-01-23,2,0,0,0,0,0
2019-01-24,0,1,0,0,0,0
2019-01-25,0,0,0,0,0,0
2019-01-26,0,0,0,0,0,0
2019-01-27,0,0,0,0,0,0
2019-01-28,0,0,0,0,0,0
2019-01-29,0,0,0,0,0,0
2019-01-30,1,0,0,0,0,0
2019-01-31,1,0,1,0,0,0
"
答案 0 :(得分:2)
第一个片段尝试结合CSV和HTML
def rank(doc_id):
...
send_file(...)
return render_template(...)
引诱,但您一次必须做一次。您可以通过执行类似的操作
来获得想要的效果(将CSV转换为D3)def rank(doc_id):
return render_template('rank.html', doc_id=doc_id, ...)
然后重新处理rank.html中嵌入的JavaScript,以在请求CSV时传递doc_id
。
d3.csv("/csv/{{doc_id}}", ...
剩下的是一条新路线
@app.route('/csv/<doc_id>')
def csv(doc_id):
...
return send_file(buffer, mimetype='text/csv')