簡體   English   中英

使用Flask將JSON數據從服務器傳遞到客戶端

[英]Passing JSON data from server to client with Flask

我對Flask完全不熟悉,並試圖弄清楚如何使用d3js強制布局顯示networkx圖形數據。 這是相關的Python代碼:

@app.route("/")
def index():
    """
    When you request the root path, you'll get the index.html template.

    """
    return flask.render_template("index.html")


@app.route("/thread")
def get_graph_data(thread_id: int=3532967):
    """
    returns json of a network graph for the specified thread
    :param thread_id:
    :return:
    """
    pqdict, userdict = graphs.get_post_quote_dict(thread_id)
    G = graphs.create_graph(pqdict)
    s = graphs.graph_to_node_link(G, remove_singlets=True) # returns dict
    return flask.jsonify(s)

這是index.html文件:

<!DOCTYPE html>
<html>
<head>
    <title>Index thing</title>
    <script type="text/javascript" src="http://d3js.org/d3.v2.js"></script>
    <link type="text/css" rel="stylesheet" href="templates/graph.css"/>
</head>
<body>
<div id="chart"></div>
<script>
    var w = 1500,
        h = 1500,
        fill = d3.scale.category20();

    var vis = d3.select("#chart")
        .append("svg:svg")
        .attr("width", w)
        .attr("height", h);

    d3.json("/thread", function (json) {
        var force = d3.layout.force()
            .charge(-120)
            .linkDistance(30)
            .nodes(json.nodes)
            .links(json.links)
            .size([w, h])
            .start();

        var link = vis.selectAll("line.link")
            .data(json.links)
            .enter().append("svg:line")
            .attr("class", "link")
            .style("stroke-width", function (d) {
                return Math.sqrt(d.value);
            })
            .attr("x1", function (d) {
                return d.source.x;
            })
            .attr("y1", function (d) {
                return d.source.y;
            })
            .attr("x2", function (d) {
                return d.target.x;
            })
            .attr("y2", function (d) {
                return d.target.y;
            });

        var node = vis.selectAll("circle.node")
            .data(json.nodes)
            .enter().append("svg:circle")
            .attr("class", "node")
            .attr("cx", function (d) {
                return d.x;
            })
            .attr("cy", function (d) {
                return d.y;
            })
            .attr("r", 5)
            .style("fill", function (d) {
                return fill(d.group);
            })
            .call(force.drag);

        vis.style("opacity", 1e-6)
            .transition()
            .duration(1000)
            .style("opacity", 1);

        force.on("tick", function () {
            link.attr("x1", function (d) {
                return d.source.x;
            })
                .attr("y1", function (d) {
                    return d.source.y;
                })
                .attr("x2", function (d) {
                    return d.target.x;
                })
                .attr("y2", function (d) {
                    return d.target.y;
                });

            node.attr("cx", function (d) {
                return d.x;
            })
                .attr("cy", function (d) {
                    return d.y;
                });
        });
    });
</script>
</body>
</html>

很明顯,d3.json()函數需要一個靜態JSON文件的位置,在這種情況下,我正在嘗試根據請求URL動態生成。

我試過了十幾種我在這里找到的方法。 根據下面的建議,我試過:

@app.route("/")
def index():
    """
    When you request the root path, you'll get the index.html template.

    """
    return flask.render_template("index.html")


@app.route("/thread")
def get_graph_data():

    """
    returns json of a network graph for the specified thread
    :param thread_id:
    :return:
    """
    thread_id = request.args.get("thread_id", 3532967, type=int)
    pqdict, userdict = graphs.get_post_quote_dict(thread_id)
    G = graphs.create_graph(pqdict)
    s = graphs.graph_to_node_link(G, remove_singlets=True)
    return jsonify(s)

模板index.html保持不變,並導航到“ http:// localhost / thread?thread_id = 12345 ”,但這失敗了,因為它在頁面上打印ID為12345的JSON而不是渲染javascript。

總而言之,我目前的目標是從URL中指定Python方法中的參數(“... / showgraph?threadid = whatever ...”),在Python代碼中生成一個json,並將其傳遞給html / js。 我該如何做到這一點?

你真的很親密!

首先,語句:“顯然d3.json()函數想要一個靜態JSON文件的位置”是不正確的。

d3.json()d3-request庫的一部分,因此是一個XHR方法(例如,需要一個URL,它可以是一個靜態JSON,如data.json ,但不是文字JSON數據)。

我會調整您的Flask路線以接受GET參數,因為該函數只會通過URL接受參數:

@app.route("/thread")
def get_graph_data():
    thread_id = request.args.get("thread_id", 3532967, type=int)
    pqdict, userdict = graphs.get_post_quote_dict(thread_id)
    G = graphs.create_graph(pqdict)
    s = graphs.graph_to_node_link(G, remove_singlets=True) # returns dict
    return flask.jsonify(s)

我的意思是,如果你想使用你需要做的函數參數:

@app.route("/thread/<int:thread_id>")
def get_graph_data(thread_id):
    ...

然后,調整您的XHR調用以發送GET參數:

var url = "/thread?thread_id=" + id.toString();
d3.json(url, function (json) {
    var force = d3.layout.force()
        .charge(-120)
        .linkDistance(30)
        .nodes(json.nodes)
        .links(json.links)
        .size([w, h])
        .start();

   // a bunch more js that i copied and pasted from a tutorial
});

它應該沒問題。

另外,僅供參考,如果您想使用Jinja2將對象“讀取”到Javascript對象中,則需要使用2個過濾器: {{ data|tojson|safe }}

解決方案是:

蟒蛇:

@app.route("/thread")
def get_graph_data():

    """
    returns json of a network graph for the specified thread
    :param thread_id:
    :return:
    """
    thread_id = request.args.get("thread_id", 3532967, type=int)
    pqdict, userdict = graphs.get_post_quote_dict(thread_id)
    G = graphs.create_graph(pqdict)
    s = graphs.graph_to_node_link(G, remove_singlets=True)
    return json.dumps(s)


@app.route("/showgraph")
def showgraph():
    thread_id = request.args.get("thread_id", 3532967, type=int)
    return render_template("index.html", threadid=thread_id)

HTML / Jinja2的:

<!DOCTYPE html>
<html>
<head>
    <title>Index thing</title>
    <script type="text/javascript" src="http://d3js.org/d3.v2.js"></script>
    <link type="text/css" rel="stylesheet" href="templates/graph.css"/>
</head>
<body>
<div id="chart"></div>
<script>
    var w = 1500,
        h = 1500,
        fill = d3.scale.category20();

    var vis = d3.select("#chart")
        .append("svg:svg")
        .attr("width", w)
        .attr("height", h);

    d3.json("/thread?thread_id={{ threadid }}", function (json) {
        var force = d3.layout.force()
            .charge(-120)
            .linkDistance(30)
            .nodes(json.nodes)
            .links(json.links)
            .size([w, h])
            .start();

        // irrelevant stuff
    });
</script>
</body>
</html>

需要單獨的方法來返回JSON並呈現頁面。 仍然似乎很傻要解析thread_id arg兩次但是無論如何。 接受PJ的答案,因為它是99%的問題!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM