Javascript ipywidgets中的子小部件创建使用ViewList和create_Child_视图产生错误 总结
请参见玩具示例Azure笔记本。笔记本可以从那里克隆并运行,也可以从那里下载并在本地运行,但为了方便起见,所有代码也都在下面 当所有单元格都运行时,javascript控制台会在最后一个单元格中报告这些错误(缩写),并且最终的预期输出行不会呈现:Javascript ipywidgets中的子小部件创建使用ViewList和create_Child_视图产生错误 总结,javascript,python,backbone.js,jupyter-notebook,ipywidgets,Javascript,Python,Backbone.js,Jupyter Notebook,Ipywidgets,请参见玩具示例Azure笔记本。笔记本可以从那里克隆并运行,也可以从那里下载并在本地运行,但为了方便起见,所有代码也都在下面 当所有单元格都运行时,javascript控制台会在最后一个单元格中报告这些错误(缩写),并且最终的预期输出行不会呈现: Error: Could not create a view for model id 91700d0eb745433eaee98bca2d9f3fc8 at promiseRejection (utils.js:119) Error: Cou
Error: Could not create a view for model id 91700d0eb745433eaee98bca2d9f3fc8
at promiseRejection (utils.js:119)
Error: Could not create view
at promiseRejection (utils.js:119)
Uncaught (in promise) TypeError: Cannot read property 'then' of undefined
Uncaught (in promise) TypeError: Cannot read property 'then' of undefined
我不知道我会错在哪里
更新:
由于当前存在,代码向create\u child\u view
方法发送字符串实例(而不是DOMWidgetModel
实例)。字符串包含由模型id附加的“IPY\u MODEL\”
。这似乎是问题的根源。客户端正在从服务器端主干子节点模型数组项(this.model.get('children')
)接收该字符串实例
我想知道这个问题是否与本文中讨论的小部件的[反]序列化有关。但我不知道如何使用它来解决这个问题,因为我需要访问子窗口小部件模型本身,而不仅仅是一个属性。我相信我正确地传递了教程指定的**widgets.widget\u序列化
细节
笔记本包含python和javascript代码,并利用了大量依赖主干的库。后端代码(python,cell#1)创建一个ipywidgets.DOMWidget
子类小部件,Test
(前端镜像的主干模型)。前端代码(javascript,cell#2)创建了一个ipywidgets.DOMWidgetView
子类,TestView
,在呈现到页面时由小部件实例化
Test
model小部件有一个children
成员,该成员由多个“子小部件”(也是模型)组成。这些小部件是python类Sub
的实例。当呈现Test
的视图时,我想实例化并呈现子窗口小部件的视图,并将它们附加到父窗口小部件Test
的视图中(注意:下面的最后一部分尚未实现)
问题是,当我尝试按照ipywidgets
API创建子视图时,通过在每个子模型上使用create\u child\u view
方法实例化子视图来填充ViewList
数组是不起作用的
这类事情的API并没有很好的文档记录,因此我将尽最大努力遵循各种类似的示例,介绍如何从父视图中使用子模型实例化子视图,例如父窗口小部件和子窗口。但是,我所做的一切似乎都无法让儿童观点的产生发挥作用
请注意,我能够单独呈现每个子小部件的视图,没有任何问题。只有当我尝试使用create\u child\u view
方法从父Test
小部件中创建视图时,我们才会遇到问题
代码
单元1(服务器端jupyter python内核)
将ipywidgets.widgets作为小部件导入
从traitlets导入Unicode、列表、实例
从IPython.display导入显示
类子(widgets.DOMWidget):
“”“要成为另一个小部件视图的一部分的小部件。”“”
_视图\u name=Unicode('SubView').tag(sync=True)
_view_module=Unicode('test').tag(sync=True)
_视图\模块\版本=Unicode('0.1.0')。标记(sync=True)
类测试(widgets.DOMWidget):
“”“打算由子窗口小部件组成的父窗口小部件。”“”
_视图\u name=Unicode('TestView').tag(sync=True)
_view_module=Unicode('test').tag(sync=True)
_视图\模块\版本=Unicode('0.1.0')。标记(sync=True)
children=List(实例(widgets.Widget)).tag(sync=True,
**widgets.widget_序列化)
def _;初始____;(自身、子系统):
super()。\uuuu init\uuuuu()
self.children=list(subs)
单元格2(前端jupyter笔记本代码)
单元格3(用于测试的python代码)
models=[Sub()表示范围(4)内的uu]
对于m in型号:
#单独查看每个子对象
显示(m)#输出:“子视图渲染”
t=试验(模型)
t#output:'rendered test_view'您需要明确地告诉前端如何反序列化小部件,即如何将字符串“IPY_MODEL”
转换为实际模型
您可以通过在前端显式定义一个模型并为子属性设置自定义反序列化器来实现这一点。这是添加到Python端的children
traitlet的**widgets.widget\u序列化
序列化程序的对应项
记事本
下面是一个笔记本的修改版本,用于呈现孩子们:
全部变化
内核方面,维护对JS模型类的显式引用:
类测试(widgets.DOMWidget):
_model_name=Unicode('TestModel').tag(sync=True)#对JS模型类的引用
_model_module=Unicode('test')。标记(sync=True)#对JS模型模块的引用
#其余的都没有变化
_视图\u name=Unicode('TestView').tag(sync=True)
_view_module=Unicode('test').tag(sync=True)
_视图\模块\版本=Unicode('0.1.0')。标记(sync=True)
children=List(实例(widgets.Widget)).tag(sync=True,**widgets.Widget\u序列化)
def _;初始____;(自身、子系统):
super()。\uuuu init\uuuuu()
self.children=subs
那么在JS方面,
导入下划线以便扩展对象:
require.unde('test');
定义('test'、[“@jupyter widgets/base”、“下划线”]、函数(widgets、389;){
定义模型模块:
var TestModel=widgets.DOMWidgetModel.extend({}{
序列化程序:\ u0.extend({
子项:{反序列化:widgets.unpack_models}
},widgets.WidgetModel.serializers)
%%javascript
require.undef('test');
define('test', ["@jupyter-widgets/base"], function(widgets) {
var SubView = widgets.DOMWidgetView.extend({
initialize: function() {
console.log('init SubView');
SubView.__super__.initialize.apply(this, arguments);
},
render: function() {
this.el.textContent = "subview rendering";
},
});
var TestView = widgets.DOMWidgetView.extend({
initialize: function() {
console.log('init TestView');
TestView.__super__.initialize.apply(this, arguments);
this.views = new widgets.ViewList(this.add_view, null, this);
this.listenTo(this.model, 'change:children', function(model, value) {
this.views.update(value);
}, this);
console.log('init TestView complete');
},
add_view: function (child_model) {
// error occurs on this line:
return this.create_child_view(child_model);
},
render: function() {
this.views.update(this.model.get('children'));
this.el.textContent = 'rendered test_view';
},
});
return {
SubView : SubView,
TestView : TestView,
};
});
subview rendering
subview rendering
subview rendering
subview rendering
subview rendering
subview rendering
subview rendering
subview rendering
rendered test_view