I am running Django 1.5.1 and Python 2.7, along with D3.js v3.

I have created a GUI where a user can dynamically add / delete nodes from a D3.js collapsable indented tree (like this block, but with buttons for add / remove). This all works fine on the browser side.

However, I would now like to save the user's changes into my database, via Django / Python. Is it possible to "export" my data from d3 and pass it to a Django view? From the documentation, it seems no, or at least I didn't see any command for it. I have tried to do a simple POST using Ajax, but the problem is that d3.selectAll returns objects...which are slightly recursive and cause my browser's stack to overflow. Example code is here:

var nodes = d3.selectAll('g.node');
var root_node = nodes[0][0].__data__;
var children = root_node.children;

    type: "POST",
    url: "update_map/",
    data: {
        'children': children,
        'bank': obj_bank_id
    success: function( result ) {
        if (result == true) {
            lscache.set( 'canvas_clean', 'true' );
        } else {
            alert( 'Error in saving data' );
    error: function( xhr, status, error ){
        alert( error );

The issue I see (using Chrome's developer tools) is that 'children' is essentially infinitely long--it is an array of objects, but within each object is a "parent" object that includes all of its children, etc. ad inifinitum. A chunk is below:

Object {source: "", item_class: "root", name: "Topics", children: Array[76], x0: 0…}
children: Array[76]
    0: Object
        _children: Array[0]
        bank: "objectivebank"
        children: null
        depth: 1
        id: 2
        item_class: "objective"
        item_id: "objective"
        name: "Antiderivative"
        parent: Object
            children: Array[76]
            depth: 0

So is there a way to get a "flat" view of all the nodes without d3 metadata either using built-in d3.js commands, or some other way? I would like something cleaner, but do I just have to save things in a separate object? Thanks!

  • 1
    Sounds to me like you have to "manually" construct the object, by initializing a blank one and then looping over the children (and their children) while building up the necessary tree. It shouldn't be that hard though. One d3 method to be aware of, if you're not already, is the .each method of a selection, which is probably what you'll want to use to loop over the children and gather their data or html strings. Also, this might be handy: within the handler of the .each loop, you can always call d3.select(this).datum() to get the data associated with a given child element. – meetamit Aug 5 '13 at 18:34
  • How many nodes are you dealing with? It seems unlikely you would overflow the call stack with a number of nodes the browser could possibly visualize. I wonder if you have a circular reference somewhere? – Scott Cameron Aug 5 '13 at 20:42
  • @ScottCameron, so there are only 77 nodes (root + 76 children). But you can see from my object snippet that the parent (plus its children) are embedded in each children object. This continues infinitely--in Firebug or Chrome, I can keep digging deeper and the levels never end. Each child (second line from the bottom) also has a parent object with 76 children, each of which has a parent with 76 children, etc. That seems to be the inherent nature of d3.js data nodes? – user Aug 6 '13 at 1:35
  • @meetamit, thanks for your tip, that lead me in the right direction! You are right--it was actually easy...the tree is constructed within the root node already, I just had to loop through and remove the "parent" attribute from each of the children to remove the recursiveness. Note that this attribute was automatically added by d3.js, not something I put in. – user Aug 6 '13 at 1:41
  • 2
    Oh, I see now. Serializing the object via jQuery.ajax is problematic because it's walking the entire object. I'm not sure what jQuery uses internally to serialize. You might be able to make some progress by setting "dataType" to "json". But more likely you'll need to serialize yourself. You can use JSON.stringify to turn the object into a string. stringify take a second arg for specifying what happens when it hits an object it has already seen. Here's a related SO question with more details: stackoverflow.com/questions/10392293/…. – Scott Cameron Aug 6 '13 at 16:20

So I solved this before seeing Scott Cameron's link to another post--JSON.stringify with the filter seems like it would definitely work and have the same functionality as what I did. Basically I created a copy of d3.selectAll('g.node') and walked through it manually, as suggested by both meetamit and Scott Cameron. I then just deleted all references to parent plus the other d3.js metadata I didn't want. I then copied the root node and viola--had my serialized tree.

        var nodes = $.extend(true, [], d3.selectAll('g.node'));

    // Only need the 'root' nodes at depth 0, because it has all the children
    //   associated with it. Just strip out the unneeded metadata...
    var remove_d3_metadata = function(node_data) {
        // remove the d3 metadata
        delete node_data.parent;
        delete node_data.x;
        delete node_data.x0;
        delete node_data.y;
        delete node_data.y0;
        delete node_data.__proto__;

        var grandchildren = node_data.children;
        if (grandchildren != null) {
            $.each( grandchildren, function(index, grandchild) {

    nodes.each( function() {
        var node_data = d3.select(this).datum();
        if (node_data.depth == 0) {
            var children = node_data.children;
            if (children != null) {
                $.each(children, function(index, child) {


Your Answer

