score:6

Accepted answer

You are really close!

First off, the statement: "clearly the d3.json() function wants a location of a static JSON file" is not correct.

d3.json() is part of the d3-request library and, as such, is an XHR method (e.g. expects a URL, which could be a static JSON like data.json, but not literal JSON data).

I would adjust your Flask route to accept a GET parameter as the function will only accept a parameter via the 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)

What I mean here is if you want to use the function parameter you'd need to do something like this:

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

Then, adjust your XHR call a bit to send the GET parameter:

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
});

And it should be fine.

Also, FYI, if you ever want to use Jinja2 to "read" an object into a Javascript Object you need to use 2 filters: {{ data|tojson|safe }}

score:3

The solution was:

Python:

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

Needed separate methods to return the JSON and render the page. Still seems silly to have to parse the thread_id arg twice but whatever. Accepted PJ's answer since it was 99% of the issue!


Related Query