odoo js
1.相关库/框架
主要:jQuery(使用1.8.3,如果使用新版本,其他jQuery插件也要升级或修改)、Underscore、QWeb
其他:都在addons\web\static\lib路径下。
2.示例框架
下载(需要先安装bzr):bzr branch lp:~niv-openerp/+junk/oepetstore -r 1
下载后将路径加到OpenERP服务器的addons_path参数中,重启服务器、更新模块列表再安装。
在__openerp__.py中通过:
'js': ['static/src/js/*.js'],
'css': ['static/src/css/*.css'],
'qweb': ['static/src/xml/*.xml'],
将所有js/css/xml(QWeb模板)文件包含进来。
oepetstore/static/js/petstore.js注释说明:
openerp.oepetstore = function(instance) { // OpenERP模型,必须和模块名称相同。instance参数是OpenERP Web Client自动加载模块时传入的实例。
var _t = instance.web._t,
_lt = instance.web._lt; // 翻译函数
var QWeb = instance.web.qweb; // QWeb实例 instance.oepetstore = {}; // instance实例里面的模块命名空间(namespace),比如和模块名称相同。 instance.oepetstore.HomePage = instance.web.Widget.extend({ // 自定义首页部件
start: function() { // 部件创建时自动调用的方法
console.log("pet store home page loaded");
},
}); instance.web.client_actions.add('petstore.homepage', 'instance.oepetstore.HomePage');
// 将自定义首页部件与菜单动作绑定
}
http://localhost:8069/?debug
3.类的定义
从instance.web.Class基类扩展:
instance.oepetstore.MyClass = instance.web.Class.extend({
say_hello: function() {
console.log("hello");
},
});
var my_object = new instance.oepetstore.MyClass();
my_object.say_hello();
构造函数名为init();使用this访问对象实例的属性或方法:
类可以通过extend()方法继承;使用this._super()调用基类被覆盖的方法。
4.部件(Widget)
从instance.web.Widget扩展自定义部件。HomePage首页部件见petstore.js。
在自定义部件中,this.$el表示部件实例的jQuery对象,可以调用jQuery方法,例如:
this.$el.append("<div>Hello dear OpenERP user!</div>");
往部件中添加一个<div>块及内容。
部件中可以插入其他部件进行组合:
父子部件可以通过getChildren()、getParent()进行互相访问。如果重载部件的构造函数,第一个参数必须是父部件,并且必须传递给基类。
instance.oepetstore.GreetingsWidget = instance.web.Widget.extend({
init: function(parent, name) {
this._super(parent);
this.name = name;
},
});
如果作为顶层部件创建,parent参数应该是null。
部件实例可以调用destroy()方法销毁。
5.QWeb模板引擎
QWeb模板在XML属性上加前缀“t-”表示:
t-name:模板名称;
t-esc:引用实例参数,可以使用任意JavaScript表达式;
t-raw:引用原始实例参数,如果有html标记则保留。
QWeb模板下面的根元素最好只有一个。
oepetstore/static/src/xml/petstore.xml:
<?xml version="1.0" encoding="UTF-8"?> <templates xml:space="preserve">
<t t-name="HomePageTemplate">
<div style="background-color: red;">
<div>Hello <t t-esc="name"/></div>
<div><t t-esc="3+5"/></div>
<div><t t-raw="some_html"/></div>
</div>
</t>
</templates>
定义一个名为“HomePageTemplate”的模板。
使用方法1:
instance.oepetstore.HomePage = instance.web.Widget.extend({
start: function() {
this.$el.append(QWeb.render("HomePageTemplate"));
},
});
使用方法2:
模板里面的条件控制t-if:
<t t-if="true == true">
true is true
</t>
<t t-if="true == false">
true is not true
</t>
枚举t-foreach和t-as:
<t t-foreach="names" t-as="name">
<div>
Hello <t t-esc="name"/>
</div>
</t>
属性赋值,在属性名前加前缀“t-att-”:
<input type="text" t-att-value="defaultName"/>
将input控件的value属性赋值为“defaultName”。
部件开发示例,显示产品列表。
JavaScript脚本:
openerp.oepetstore = function(instance) {
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb; instance.oepetstore = {}; instance.oepetstore.HomePage = instance.web.Widget.extend({
start: function() {
var products = new instance.oepetstore.ProductsWidget(this, ["cpu", "mouse", "keyboard", "graphic card", "screen"], "#00FF00");
products.appendTo(this.$el);
},
}); instance.oepetstore.ProductsWidget = instance.web.Widget.extend({
template: "ProductsWidget",
init: function(parent, products, color) {
this._super(parent);
this.products = products;
this.color = color;
},
}); instance.web.client_actions.add('petstore.homepage', 'instance.oepetstore.HomePage');
}
QWeb模板:
<?xml version="1.0" encoding="UTF-8"?> <templates xml:space="preserve">
<t t-name="ProductsWidget">
<div>
<t t-foreach="widget.products" t-as="product">
<span class="oe_products_item" t-att-style="'background-color: ' + widget.color + ';'"><t t-esc="product"/></span><br/>
</t>
</div>
</t>
</templates>
CSS样式:
6.部件事件与特性
instance.oepetstore.ConfirmWidget = instance.web.Widget.extend({
start: function() {
var self = this;
this.$el.append("<div>Are you sure you want to perform this action?</div>" +
"<button class='ok_button'>Ok</button>" +
"<button class='cancel_button'>Cancel</button>");
this.$el.find("button.ok_button").click(function() { // 在按钮上绑定click事件
self.trigger("user_choose", true); // 触发自定义user_choose事件,传递事件参数true/false
});
this.$el.find("button.cancel_button").click(function() {
self.trigger("user_choose", false);
});
},
}); instance.oepetstore.HomePage = instance.web.Widget.extend({
start: function() {
var widget = new instance.oepetstore.ConfirmWidget(this);
widget.on("user_choose", this, this.user_choose); // 在部件上绑定user_choose事件到响应函数user_choose
widget.appendTo(this.$el);
},
user_choose: function(confirm) {
if (confirm) {
console.log("The user agreed to continue");
} else {
console.log("The user refused to continue");
}
},
});
部件特性(Properties)的使用:
this.widget.on("change:name", this, this.name_changed); //绑定name特性的change事件
this.widget.set("name", "Nicolas"); // 设置特性值
var getedname = this.widget.get("name"); // 读取特性值
7.部件访问 简化jQuery选择器:
this.$el.find("input.my_input")
等于
this.$("input.my_input")
因此事件的绑定:
this.$el.find("input").change(function() {
self.input_changed();
});
可以简化为:
进一步,可以通过部件提供的events字典属性简化为:
instance.oepetstore.MyWidget = instance.web.Widget.extend({
events: {
"click .my_button": "button_clicked",
},
button_clicked: function() {
..
}
});
注意:这种方法只是绑定jQuery提供的DOM事件机制,不能用于部件的on语法绑定部件自身的事件。 event属性的键名由两部分组成:事件名称和jQuery选择器,用空格分开。属性值是响应事件的函数(方法)。
事件使用示例:
JavaScript脚本:
openerp.oepetstore = function(instance) {
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb; instance.oepetstore = {}; instance.oepetstore.ColorInputWidget = instance.web.Widget.extend({
template: "ColorInputWidget",
start: function() {
var self = this;
this.$el.find("input").change(function() {
self.input_changed();
});
self.input_changed();
},
input_changed: function() {
var color = "#";
color += this.$el.find(".oe_color_red").val();
color += this.$el.find(".oe_color_green").val();
color += this.$el.find(".oe_color_blue").val();
this.set("color", color);
},
}); instance.oepetstore.HomePage = instance.web.Widget.extend({
template: "HomePage",
start: function() {
this.colorInput = new instance.oepetstore.ColorInputWidget(this);
this.colorInput.on("change:color", this, this.color_changed);
this.colorInput.appendTo(this.$el);
},
color_changed: function() {
this.$el.find(".oe_color_div").css("background-color", this.colorInput.get("color"));
},
}); instance.web.client_actions.add('petstore.homepage', 'instance.oepetstore.HomePage');
}
QWeb模板:
<?xml version="1.0" encoding="UTF-8"?> <templates xml:space="preserve">
<t t-name="ColorInputWidget">
<div>
Red: <input type="text" class="oe_color_red" value="00"></input><br />
Green: <input type="text" class="oe_color_green" value="00"></input><br />
Blue: <input type="text" class="oe_color_blue" value="00"></input><br />
</div>
</t>
<t t-name="HomePage">
<div>
<div class="oe_color_div"></div>
</div>
</t>
</templates>
CSS样式:
.oe_color_div {
width: 100px;
height: 100px;
margin: 10px;
}
8.修改已有的部件和类
可以用include()方法重载已有的部件和类,这个和继承机制类似,是一种插入的方法:
应尽量避免使用这种机制导致的复杂性。
9.与服务器的交互-读取数据模型
客户端使用Ajax与服务器交互,不过OpenERP框架提供了简化的方法,通过数据模型进行访问。
OpenERP自动将服务端的数据模型转化为客户端端模型,直接调用即可。服务器上petstore.py里面的模型:
class message_of_the_day(osv.osv):
_name = "message_of_the_day" def my_method(self, cr, uid, context=None):
return {"hello": "world"} _columns = {
'message': fields.text(string="Message"),
'color': fields.char(string="Color", size=20),
}
客户端调用例子:
instance.oepetstore.HomePage = instance.web.Widget.extend({
start: function() {
var self = this;
var model = new instance.web.Model("message_of_the_day");
model.call("my_method", [], {context: new instance.web.CompoundContext()}).then(function(result) {
self.$el.append("<div>Hello " + result["hello"] + "</div>");
// will show "Hello world" to the user
});
},
});
模型的call()方法参数:
第一个参数name是方法的名称;
第二个参数args是按照顺序排列的参数数组。OpenERP定义的模型方法前三个参数(self, cr, uid)是固定的,由框架产生,也就是说传递的参数数组从第四个开始插入。而context又是特殊的。例子:
方法定义:
def my_method2(self, cr, uid, a, b, c, context=None):
调用:
第三个参数kwargs为命名参数,按照名称传递给Python的方法参数。例如:
OpenERP模型中的context是一个特殊参数,表示调用者的上下文,一般就使用客户端Web Client实例提供的instance.web.CompoundContext()类新建一个对象实例即可。
CompoundContext类提供用户的语言和时区信息。也可以在构造函数中添加另外的数据:
(OpenERP服务器端数据模型的方法必须提供4个参数:self, cr, uid, context=None,分别表示模型实例、数据库指针(Cursor)、用户id和用户上下文)
10.与服务器的交互-查询
客户端数据模型提供了search()、read()等方法,组合为query()方法,使用例子:
model.query(['name', 'login', 'user_email', 'signature']) .filter([['active', '=', true], ['company_id', '=', main_company]]) .limit(15) .all().then(function (users) { // do work with users records});
数据模型的query()方法的参数是需要读取的模型字段名称列表;该方法返回的是一个instance.web.Query()类型的查询对象实例,包括一些进一步定义查询结果的方法,这些方法返回的是同一个查询对象自身,因此可以链接:
filter():指定OpenERP 域(domain),也即过滤查询结果;
limit():限制返回的记录数量。
最后调用查询对象的all()方法执行查询。
查询异步执行,all()返回的是一个deferred,因此要用then()提供回调函数来处理结果。
数据模型的查询是通过rpc调用实现的。
示例1:显示每日提示
JavaScript脚本:
QWeb模板:
CSS样式:
示例2:组合显示每日提示和产品列表
服务器端从OpenERP的产品表继承一个类(模型):
因此数据是保存在product.product表中的,只是扩充了一个“max_quantity”字段;这个例子结合前面的每日提示信息,显示二列,左面一列显示产品列表,右面显示提示信息。
JavaScript脚本:
openerp.oepetstore = function(instance) {
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb; instance.oepetstore = {}; instance.oepetstore.HomePage = instance.web.Widget.extend({
template: "HomePage",
start: function() {
var pettoys = new instance.oepetstore.PetToysList(this);
pettoys.appendTo(this.$(".oe_petstore_homepage_left"));
var motd = new instance.oepetstore.MessageOfTheDay(this);
motd.appendTo(this.$(".oe_petstore_homepage_right"));
},
}); instance.web.client_actions.add('petstore.homepage', 'instance.oepetstore.HomePage'); instance.oepetstore.MessageOfTheDay = instance.web.Widget.extend({
template: "MessageofTheDay",
init: function() {
this._super.apply(this, arguments);
},
start: function() {
var self = this;
new instance.web.Model("message_of_the_day").query(["message"]).first().then(function(result) {
self.$(".oe_mywidget_message_of_the_day").text(result.message);
});
},
}); instance.oepetstore.PetToysList = instance.web.Widget.extend({
template: "PetToysList",
start: function() {
var self = this;
new instance.web.Model("product.product").query(["name", "image"])
.filter([["categ_id.name", "=", "Pet Toys"]]).limit(5).all().then(function(result) {
_.each(result, function(item) {
var $item = $(QWeb.render("PetToy", {item: item}));
self.$el.append($item);
});
});
},
}); }
QWeb模板:
CSS样式:
odoo js的更多相关文章
- odoo widgets.js 笔记
// 在OpenERP的Web框架内, // 通过声明一个函数来声明一个JavaScript模块[openerp.ext_picking就是这个JS模块], // 并把这个函数放在全局变量opener ...
- Odoo 二次开发教程(二)-模块的基础构建
注:本篇及后续均以8.0为基础. 一. Odoo模块的构成 __init__.py 文件是python包导入所必须的文件,内容可以为空,通常情况下我们用来导入自己写的py文件. __openerp__ ...
- odoo模块
odoo模块包括 业务对象,web控制器,数据文件,前面2个是Python模块,而数据文件则是odoo特有的文件,例如,odoo数据文件,web数据.这些数据文件在 __odoo__.py 进行定义, ...
- Odoo中的Javascript单元测试
前端页面利用QUnit进行单元测试,本文参考官方文档:https://www.odoo.com/documentation/8.0/reference/javascript.html 访问/web/t ...
- (21)odoo中的QWeb模板引擎
-----------------更新时间18:13 2016-04-05 星期二-----------------* 概述 QWeb是odoo主要模板引擎,采用xml表述,最后生成HTML文件 ...
- (20)odoo中的action
---------更新时间18:06 2016-09-18 星期日15:05 2016-03-14 星期一18:07 2016-02-19 星期五---------* 窗口动作 <?xml ...
- (19)odoo中的javascript
-----------更新日期15:17 2016-02-16 星期二-----------* 用到的js库 我们可以打开 addons/web/views/webclient_template. ...
- (02)odoo自定义模块
* 官方建议模块骨架 -------------------------- addons/<my_module_name>/ │─ __init ...
- Odoo 开发者模式
这里我们以Odoo V9介绍下Odoo的开发者模式: 进入开发者模式: 登录odoo系统后,点击右上角登陆账号下拉菜单,选择About,然后在弹出菜单里点击Activate the developer ...
随机推荐
- 数学相关比较 牛顿迭代法求开方 很多个n的平方分之一
牛顿迭代法求开方 牛顿迭代法 作用: 求f(x) = 0 的解 方法:假设任意一点 x0, 求切线与x轴交点坐标x1, 再求切线与x轴交点坐标x2,一直重复,直到f(xn) 与0的差距在一个极小的范围 ...
- sql2000行转列 转过来的测试完也不知那个网站去哪了 没法写出处了
ALTER procedure dbo.CommonRowToCol ) as begin --必须包含colname列和result列(不区分大小写), --除colname列和result列 其余 ...
- Python匹马行天下之python之父
龟叔和他的python 经过了漫长的旅程,终于要看到主角Python了.Python是现在非常非常流行的编程语言,在我们能看到的大部分编程语言排行榜中,Python都能在前三甲中拥有一席之地 ,并且发 ...
- identityserver4 对接钉钉
参考了https://www.cnblogs.com/sheldon-lou/p/10643267.html
- vue3+node全栈项目部署到云服务器
一.前言 最近在B站学习了一下全栈开发,使用到的技术栈是Vue+Element+Express+MongoDB,为了让自己学的第一个全栈项目落地,于是想着把该项目部署到阿里云服务器.经过网上一番搜索和 ...
- smb中继攻击
一.NTLM hash 和 Net-NTLM hash 1.客户端向服务器发送一个请求,请求中包含明文的登录用户名.服务器会提前保存登录用户名和对应的密码 hash 2.服务器接收到请求后,生成一个 ...
- leetcode-227-基本计算器②
题目描述: 方法一:中缀转后缀 #!_*_coding:utf-8_*_ class Solution: def calculate(self, s: str) -> int: def in_t ...
- Android App上架流程
想要把APP上架到应用市场都要先注册开发者账号才可以.这里的方法包括注册帐号和后期上架及一些需要注意的问题.注意:首次提交应用绝对不能随便删除,否则后面再提交会显示应用APP冲突,会要求走应用认领流程 ...
- for循环和字典预习
print("*" *8)for a in range(1,9): print(a,end="")#1-9的奇数print()for a in range(1, ...
- JavaScript中的表单编程
表单编程 1获取表单相关信息 1.什么是表单元素 1.什么是表单元素 在H TML中表单就是指form标签,它的作用是将用户输入或选择的数据提交给指定的服务器 2.如何获取表单元素 <form ...