Flask - Напишите временный CSV для чтения D3 - PullRequest
0 голосов
/ 30 апреля 2019

В настоящее время я пытаюсь написать файл CSV во Flask, используя Pandas, который затем должен быть прочитан D3.js. Однако файл CSV не создается, и я получаю сообщения об ошибках http://127.0.0.1:5000/test.csv 500 (INTERNAL SERVER ERROR) и Uncaught ProgressEvent, которые, как я понимаю, связаны с тем, что файл CSV не может быть найден.

Я пробовал разные решения, а именно пытался написать CSV с использованием dataframe.to_csv(path), но файл никогда не генерировался и ошибок не возвращалось.

Я также пытался использовать буфер и встроенный метод 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', ...)

1020 * 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(...).

CSV Я должен получить то, что получаю от var rankingscsv= '{{ rankingscsv|tojson|safe }}';

"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
"

1 Ответ

2 голосов
/ 30 апреля 2019

Первый фрагмент пытается объединить 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, ...)

Затем переработайте JavaScript, встроенный в rank.html, для передачи doc_id при запросе CSV.

d3.csv("/csv/{{doc_id}}", ...

Новый маршрут делает все остальное

@app.route('/csv/<doc_id>')
def csv(doc_id):
    ...
    return send_file(buffer, mimetype='text/csv')
...