2013-08-05 119 views
2

我正在Django的1.5.1和Python 2.7,与D3.js V3一起。D3.js “出口” 的数据

我创建了一个GUI,用户可以从D3.js可折叠缩进树(如block,但带有用于添加/删除的按钮)动态添加/删除节点。这一切都在浏览器端正常工作。

不过,我现在想给用户的更改保存到我的数据库,通过Django的/ Python的。是否有可能从d3“导出”我的数据并将其传递给Django视图?从documentation,似乎没有,或者至少我没有看到任何指令。我试图用Ajax做一个简单的POST,但问题是d3.selectAll返回对象......这些对象稍微递归,导致浏览器堆栈溢出。示例代码是在这里:

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

$.ajax({ 
    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); 
    } 
}); 

我看到(使用Chrome的开发者工具)的问题是,“孩子”基本上是无限长的 - 它是对象的数组,但每个对象中是一个“父”对象包括所有的孩子,等等。块是如下:

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 

那么,有没有办法让所有节点的“平面”视图,而不D3元或者使用内置的d3.js命令,或者一些其他的方式?我想要更清洁的东西,但是我只需要将东西保存在单独的对象中?谢谢! JSON.stringify与过滤好像它肯定会工作,并具有相同的功能我做了什么 -

+1

听起来像你对我有“手工”构造对象,通过初始化为空白,然后遍历孩子(和他们的孩子),同时建立必要的树。这不应该那么难。一种D3方法需要注意的,如果你没有准备好,是'一个选择,这可能是你要在孩子使用循环并收集他们的数据或HTML串什么的.each'方法。此外,这可能是得心应手:在'.each'循环的处理程序中,可以随时拨打'd3.select(本).datum()'来获得与给定的子元素相关的数据。 – meetamit

+0

你处理了多少个节点?看起来你不太可能会用一些浏览器可能可视化的节点溢出调用堆栈。我想知道你是否有循环引用? –

+0

@ScottCameron,所以只有77个节点(root + 76个孩子)。但是你可以从我的对象片断中看到父对象(加上它的子对象)嵌入到每个子对象中。这个过程无限延续 - 在Firebug或Chrome中,我可以继续深入挖掘,并且层次永远不会结束。每个孩子(从底部开始的第二行)也有一个有76个孩子的父对象,每个孩子有一个拥有76个孩子的父母,等等。这似乎是d3.js数据节点的固有特性? – user

回答

1

所以我看到斯科特·卡梅隆的链接到其他岗位之前解决了这个。基本上我创建了d3.selectAll('g.node')的副本,并按照meetamit和Scott Cameron的建议手动完成。然后,我删除了所有对父项的引用,以及我不想要的其他d3.js元数据。然后我复制了根节点和中提琴 - 让我的序列化树。

 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) { 
       remove_d3_metadata(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) { 
        remove_d3_metadata(child); 
       }); 
      } 
     } 
    }); 

    var root_node = nodes[0][0].__data__;