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');  
    // 將自定義首頁部件與菜單動作綁定  
}  
  可以在網址后面加“?debug”參數使腳本不壓縮以便於調試,例如:
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訪問對象實例的屬性或方法:
instance.oepetstore.MyClass = instance.web.Class.extend({  
    init: function(name) {  
        this.name = name;  
    },  
    say_hello: function() {  
        console.log("hello", this.name);  
    },  
});  
  
var my_object = new instance.oepetstore.MyClass("Nicolas");  
my_object.say_hello();  
  類可以通過extend()方法繼承;使用this._super()調用基類被覆蓋的方法。
instance.oepetstore.MySpanishClass = instance.oepetstore.MyClass.extend({  
    say_hello: function() {  
        this._super();  
        console.log("translation in Spanish: hola", this.name);  
    },  
});  
  
var my_object = new instance.oepetstore.MySpanishClass("Nicolas");  
my_object.say_hello();  
4.部件(Widget)
  從instance.web.Widget擴展自定義部件。HomePage首頁部件見petstore.js。
  在自定義部件中,this.$el表示部件實例的jQuery對象,可以調用jQuery方法,例如:
this.$el.append("<div>Hello dear OpenERP user!</div>");  
  往部件中添加一個<div>塊及內容。
  部件中可以插入其他部件進行組合:
instance.oepetstore.GreetingsWidget = instance.web.Widget.extend({  
    start: function() {  
        this.$el.addClass("oe_petstore_greetings");  
        this.$el.append("<div>We are so happy to see you again in this menu!</div>");  
    },  
});  
instance.oepetstore.HomePage = instance.web.Widget.extend({  
    start: function() {  
        this.$el.addClass("oe_petstore_homepage");  
        this.$el.append("<div>Hello dear OpenERP user!</div>");  
        var greeting = new instance.oepetstore.GreetingsWidget(this); // 創建部件的時候傳入父部件的實例作為構造參數。  
        greeting.appendTo(this.$el);  
    },  
});  
  父子部件可以通過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:
instance.oepetstore.HomePage = instance.web.Widget.extend({  
    template: "HomePageTemplate",  
    start: function() {  
        ...  
    },  
});  
  模板里面的條件控制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樣式:
.oe_products_item {  
    display: inline-block;  
    padding: 3px;  
    margin: 5px;  
    border: 1px solid black;  
    border-radius: 3px;  
}  
  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();  
            });  
  可以簡化為:
this.$(".my_button").click(function() {  
            self.button_clicked();  
        });  
  進一步,可以通過部件提供的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()方法重載已有的部件和類,這個和繼承機制類似,是一種插入的方法:
var TestClass = instance.web.Class.extend({  
    testMethod: function() {  
        return "hello";  
    },  
});  
  
TestClass.include({  
    testMethod: function() {  
        return this._super() + " world";  
    },  
});  
  
console.log(new TestClass().testMethod());  
// will print "hello world"  
  應盡量避免使用這種機制導致的復雜性。

  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):  
  調用:
 
model.call("my_method", [1, 2, 3], ...// with this a=1, b=2 and c=3  

    第三個參數kwargs為命名參數,按照名稱傳遞給Python的方法參數。例如:
model.call("my_method", [], {a: 1, b: 2, c: 3}, ...// with this a=1, b=2 and c=3  
 
  OpenERP模型中的context是一個特殊參數,表示調用者的上下文,一般就使用客戶端Web Client實例提供的instance.web.CompoundContext()類新建一個對象實例即可。
  CompoundContext類提供用戶的語言和時區信息。也可以在構造函數中添加另外的數據:
model.call("my_method", [], {context: new instance.web.CompoundContext({'new_key': 'key_value'})})def display_context(self, cr, uid, context=None):    print context    // will print: {'lang': 'en_US', 'new_key': 'key_value', 'tz': 'Europe/Brussels', 'uid': 1}  
  (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腳本:
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 motd = new instance.oepetstore.MessageOfTheDay(this);  
            motd.appendTo(this.$el);  
        },  
    });  
  
    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);  
            });  
        },  
    });  
  
}  
  QWeb模板:
<?xml version="1.0" encoding="UTF-8"?>  
  
<templates xml:space="preserve">  
    <t t-name="HomePage">  
        <div class="oe_petstore_homepage">  
        </div>  
    </t>  
    <t t-name="MessageofTheDay">  
        <div class="oe_petstore_motd">  
            <p class="oe_mywidget_message_of_the_day"></p>  
        </div>  
    </t>  
</templates>  
  CSS樣式:
.oe_petstore_motd {  
    margin: 5px;  
    padding: 5px;  
    border-radius: 3px;  
    background-color: #F0EEEE;  
}  
  示例2:組合顯示每日提示和產品列表
  服務器端從OpenERP的產品表繼承一個類(模型):
class product(osv.osv):  
       _inherit = "product.product"  
    
       _columns = {  
           'max_quantity': fields.float(string="Max Quantity"),  
       }  
  因此數據是保存在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模板:
<?xml version="1.0" encoding="UTF-8"?>  
  
<templates xml:space="preserve">  
    <t t-name="HomePage">  
        <div class="oe_petstore_homepage">  
            <div class="oe_petstore_homepage_left"></div>  
            <div class="oe_petstore_homepage_right"></div>  
        </div>  
    </t>  
    <t t-name="MessageofTheDay">  
        <div class="oe_petstore_motd">  
            <p class="oe_mywidget_message_of_the_day"></p>  
        </div>  
    </t>  
    <t t-name="PetToysList">  
        <div class="oe_petstore_pettoyslist">  
        </div>  
    </t>  
    <t t-name="PetToy">  
        <div class="oe_petstore_pettoy">  
            <p><t t-esc="item.name"/></p>  
            <p><img t-att-src="'data:image/jpg;base64,'+item.image"/></p>  
        </div>  
    </t>  
</templates>  
  CSS樣式:
.oe_petstore_homepage {  
    display: table;  
}  
  
.oe_petstore_homepage_left {  
    display: table-cell;  
    width : 300px;  
}  
  
.oe_petstore_homepage_right {  
    display: table-cell;  
    width : 300px;  
}  
  
.oe_petstore_motd {  
    margin: 5px;  
    padding: 5px;  
    border-radius: 3px;  
    background-color: #F0EEEE;  
}  
  
.oe_petstore_pettoyslist {  
    padding: 5px;  
}  
  
.oe_petstore_pettoy {  
    margin: 5px;  
    padding: 5px;  
    border-radius: 3px;  
    background-color: #F0EEEE;  
}  
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM