现在已经将jupyter放进iframe里面,现在的问题描述为:在父页面获取iframe里面的内容,iframe里面就是jupyter,这里的父页面是自己搭建的tornado服务器打开的页面,网址为127.0.0.1:9000,iframe里面的jupyter用的网址是127.0.0.1:8888,所以涉及到了跨域请求。
父页面获取iframe里面内容的解决方案如下:
实验如下:开两个tornado服务器,一个端口9000,一个端口9001
现在在9000页面要放一个iframe指向9001的一个页面,再在9000父页面打印9001iframe里面的东西是访问不了的,提示跨域了,端口不一样
目标父页面127.0.0.1:9000访问自己iframe src=127.0.0.1:9001里面的内容
解决这个问题的方案的思路:
1、在127.0.0.1:9000页面使用js代码动态增加一个iframe其src是与127.0.0.1:9001同级目录下的一个页面127.0.0.1:9001/execB.html
2、然后先去9001创建好这个页面execB.html配置好url,保证能访问到。
3、在127.0.0.1:9001/execB.html中,去做想做的js操作(如调用127.0.0.1:9001中的一个js函数,或者改变背景色等都在这个页面进行)
原理解释:9000页面现在有两个iframe,一个访问9001,一个是动态增加的访问9001/execB.html,9000加载完后返回9001的
….标签,此时,9001/execB.html也返回了,但是9001/execB.html里面有操作9001的DOM的js代码如:parent.window.frames[“myframe9000”].document.getElementById(“test”).innerHTML,这样就相当于9001/execB.html再操作9001里面的DOM,就能够操作成功
127.0.0.1:9000
html代码:
js代码:
window.οnlοad=function (ev) {
function exec_iframe(){
if(typeof(exec_obj)=='undefined'){
exec_obj = document.createElement('iframe');
exec_obj.name = 'tmp_frame';
exec_obj.src = 'http://127.0.0.1:9001/execB';
exec_obj.style.display = 'none';
document.body.appendChild(exec_obj);//动态创建一个iframe
}else{
exec_obj.src = 'http://127.0.0.1:9001/execB?' + Math.random();
}
}
exec_iframe()
}
127.0.0.1 :9001
html代码(目标id=notebook里面的内容被获取,被显示,颜色更改):
Title
test9001
这个页面放到iframe里面,目标获取这里的内容就算成功
127.0.0.1:9001/execB.html(真正做取值的js页面,被动态添加到9000页面iframe)
js代码(去操作同一个域名下的127.0.0.1:9001的内容获取id=notebook里面的内容):
Title
至此,跨域访问成功~
发现其实jupyter自身还有一层保护,通过阅读文档发现,还要去设置jupyter被引用的域名是谁。
(同时可以阅读源码:notebook/base/handlers.py 从62行开始定义了content_security_policy函数的操作,有相同描述,下文有解释。)
如果不添加上面的这串代码,在自己写的父页面里写
将会导致下图1这里都打不开,将会显示图2这种东西,就是self指向是不对的,不允许其他的页面的iframe指向自己
图1
图2
那么添加了下面这串之后一切显示正常。但是现在的需求是获取iframe的值,然后好在tornado服务端存入数据库,好跟踪记录学生的学习情况。
使用1种所说的解决跨域的方案。在jupyter目录下建立execB.html,让这个execB.html去操作jupyter里面的DOM获取里面的元素。本来是可以实现的。结果jupyter内部的content_security_policy定义的策略,让execB.html也成了允许范围之外的人
在notebook/base/handlers.py里面说的很清楚,如下图:
就是说,如果settings定义了headers就用它的,那我们现在是定义了的(就是上面让定义的在这里:~.jupyter/jupyter_notebook_config.py,如过不定义自己的tornado服务器的页面里的iframe显示不了,但是这里必须显示出来,不然没意义)但是现在定义了,因为execB.html也是一个动态创建的iframe,它又显示不了。现在这种跨域取值的方式因为jupyter自身安全保护的机制取不了值。只有换一种思路~~~~
我现在想在jupyter(随意打开一个jupyter notebook http://127.0.0.1:8888/notebooks/test2.ipynb)中获取了值(学生通过jupyter打印的返回结果)之后,通过更改jupyter源码,在源码中添加ajax方式,在jupyter中将获取的结果传给我自己的tornado服务端,然后就可以美滋滋的将学生操作的结果值存数据库了。
需求:将jupyter notebook中打印的结果传到自己的tornado服务端,在tornado服务端写sql语句将jupyter notebook前端页面传递过来的数据保存,方便显示到其他地方(二次开发jupyter notebook,将其结果作为一种使用jupyter的学生的操作反馈显示在网站后台)
window.οnlοad=function () {
//var temp_result = $("#notebook div[class ~='selected'] .output_wrapper .output .output_text pre").text())
var temp_result = $("#notebook .output_wrapper .output .output_text pre").text()
console.log(temp_result)
}
notebook/templates/notebook.html中添加ajax请求的代码
class AjaxjupyterHandler(HomeHandler):
def get(self):
temp_result = self.get_argument("temp_result", "")
callbackfun = self.get_argument("callbackfun", "") #接受callback的名字callbackfun=jsonpCallback
res = dict()
res["status"] = 0
res["info"] = "添加成功"
res["temp_result"] = temp_result
self.set_header("content-type", "application/json")
data = json.dumps(res)