-
~/cli/server.py
, ln 320, main(args) -
~/cli/server.py
, ln 366, openerp.service.start_services_workers() 或 openerp.service.start_services() -
以
-
start_internal() 1.1 openerp.osv.osv.start_object_proxy() 1.2 web_services.start_service() 1.3 load_server_wide_modules(),openerp.modules.module.load_openerp_module 1.4 加载
web
后会通过postload
去执行 openerp.addons.web.http.wsgi_postload 1.5 在初始化的过程中会更新openerp.addons.web.http
里的addons_module
,addons_manifest
,controllers_class
,controllers_class_path
,controllers_object
,controllers_object_path
, controllers_path 这些全局可见的变量,魔改的想象空间很大 1.6openerp.wsgi.register_wsgi_handler(Root())
生成一个 wsgi app 并注册,实际的 app 是 Root.dispatch 1.7Root.__init__
会self.load_addons
,凡是在路径下的所有 addon 都会被加载,也就是说所有语句都会被执行,好可怕 1.8_cp_path
相当于 Blueprint,其后的部分匹配为 method 1.9 没有区分 GET POST 等,而且按照注释看来,无论参数都会被统一处理到同一个地方 -
wsgi_server.start_service()
-
cron.start_service()
通过多进程起的,暂时没有打到断点
- 当前用户使用的语言
_oe_instance.session.user_context.lang
-
对于
oe 网页服务
来说,base
不是基础模块,web
才是(cli
的情况不清楚) 1.1 更确切的说,默认值是 ['web', 'web_kanban'] // ~/openerp/tools/config.py, line 526 -
加载过程的主要代码在
~/openerp/addons/web/controllers/main.py, line 247, module_boot
及相关代码 2.1. 首先加载网页服务
的基础模块,然后加载本数据库中已安装的addons
2.2.网页服务
的基础模块,即['web', 'web_kanban']
确定是最先加载的 2.3. 已安装的addons
按照依赖关系,最终的加载顺序是按照 Topsort 排序的结果;该排序的结果是是“被依赖模块”确定在“依赖模块”的前面;但考虑到复杂的深层依赖关系,以及实际安装addon
的顺序不同,这个排序的结果实际上是不稳定的;也就是说除了好好分析依赖关系和写清楚依赖关系,没有其它途径可以预期最终的加载行为 -
然后根据
addon
的顺序,以及addon
内__openerp__.py
中写清楚的静态文件加载顺序进行依次加载 3.1 如果AddonA
依赖于AddonB
,那么AddonB
中设定的js, css
全部在AddonA
之前加载 3.2 如果在AddonA
中设定'js': ['1.js', '2.js']
,那么1.js
在2.js
之前加载 -
最终的模块加载效果可以在
window.openerp.instances.instance0
里查看 -
不是所有已安装的模块都会被“加载”,比如
product
就不会出现在上面这个列表里
-
官方的原生视图包括
tree/list
,form
;kanban
是扩展出来的,所以如果要自定义视图,主要参考kanban
的实现 -
主要需要
override
的属性和方法如下(命名规则随手写的,不保证对):instance.nt_my_addon.CustomView = instance.web.View.extend({ searchable: false, template: 'nt_my_addon.custom_view_tpl', display_name: 'Custom View', view_type: 'custom_view', init: function (parent, dataset, view_id, options) {}, start : function () { // 不要去 call this._super,完全自己控制 }, do_show: function () { // 详见 nt_bwk_flowchart this._super.apply(this, arguments); }, destroy: function () { }, }); instance.web.views.add('CustomView', 'instance.nt_my_addon.CustomeView');
-
原始菜单一般会指向 tree view,并且不知道 custom view 的存在,因此需要自定义菜单,并覆盖或隐藏掉原始菜单
<record id="nt_my_addon_custom_view" model="ir.ui.view"> <field name="name">nt.my_addon.custom_view</field> <field name="model">model.to.display</field> </record> <record id="nt_my_addon_tree_action"> <field name="name">Model Name</field> <field name="type">ir.actions.act_window</field> <field name="res_model">model.to.display</field> <field name="view_type">form</field> <field name="view_mode">tree,form,kanban,nt_my_addon_custom_view</field> </record> <menuitem name="Model Name" id="nt_my_addon_model_name" parent="nt_my_addon_root" action="nt_my_addon_tree_action" />
-
以
FormView
为例:- 在视图之间切换的时候,首先调用基类
instance.web.view
的switch_mode
方法,目的是做lazy loading
;完成后调当前类的do_show
方法;获取数据后调用当前类的load_record
- 在记录之间切换的时候,首先调用当前类的
execute_pager_action
方法,然后调用reload
,获取数据后调用load_record
- 上述调用都是用的
event dispatcher
,不知道为什么;可能是Backbone
的编码风格
- 在视图之间切换的时候,首先调用基类
-
官方接口提供了基于后端
ORM
的语义化查询,返回值是基于jQuery
的Deferred
(没细看版本,反正要重新封装)var _adapter = new oe_instance.web.Model('res.users'); _adapter .query(['name', 'login', 'user_email', 'signature']) .filter(['active', '=', true], ['company_id', '=', main_company]]) .limit(15) .all() .then(function (data) { // });
-
或者直接调用
Model
上的方法_adapter .call('change_password', ['oldpassword', 'newpassword'], { context: some_context }) .then(function (data) { // }); // 相当于后端的 user_obj = self.pool.get('res.user') user_obj.change_password(cr, uid, oldpassword, newpassword, context=some_context)
-
当前的
context
var _context = _adapter.context();
参考:
####do_action(action, options)
/addons/web/static/src/js/views.js
line 295
-
假如不传参数,那么默认行为是
ir.actions.act_window_close
-
假如你知道要跳转到哪 个
action
,直接跳id
是最准确的,得到的是identical
的结果 oe_this.do_action('base.action_partner_form') -
对于
dialog
,可以在options
里面设定on_close
方法,没有传入值oe.this.do_action(action, { on_close: function () { console.assert(arguments.length === 0); } })
参考:
- (official) OpenERP Web Components - The Action Manager