• (19)odoo中的javascript


    -----------
    更新日期
    15:17 2016-02-16 星期二
    -----------
    * 用到的js库
       我们可以打开 addons/web/views/webclient_template.xml
       看到如下:
            <template id="web.assets_common">
                <script type="text/javascript" src="/web/static/lib/es5-shim/es5-shim.min.js"></script>
                <script type="text/javascript" src="/web/static/lib/underscore/underscore.js"></script>
                <script type="text/javascript" src="/web/static/lib/underscore.string/lib/underscore.string.js"></script>
                <script type="text/javascript" src="/web/static/lib/datejs/globalization/en-US.js"></script>
                <script type="text/javascript" src="/web/static/lib/spinjs/spin.js"></script>

                <!-- jQuery stuff -->
                <script type="text/javascript" src="/web/static/lib/jquery/jquery.js"></script>
                <script type="text/javascript" src="/web/static/lib/jquery.blockUI/jquery.blockUI.js"></script>
                <script type="text/javascript" src="/web/static/lib/jquery.hotkeys/jquery.hotkeys.js"></script>
                <script type="text/javascript" src="/web/static/lib/jquery.placeholder/jquery.placeholder.js"></script>
                <script type="text/javascript" src="/web/static/lib/jquery.timeago/jquery.timeago.js"></script>
                <script type="text/javascript" src="/web/static/lib/jquery.form/jquery.form.js"></script>

                <script type="text/javascript" src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script>

                <script type="text/javascript" src="/web/static/lib/qweb/qweb2.js"></script>
                <script type="text/javascript" src="/web/static/src/js/openerpframework.js"></script>
                <script type="text/javascript" src="/web/static/src/js/tour.js"></script>

                <link rel="stylesheet" href="/web/static/lib/fontawesome/css/font-awesome.css"/>
            </template>
            # es5-shim 给傻逼浏览器做兼容性,使得傻逼浏览器可以支持一些 es5 的 api
            # spinjs  ajax异步时,等待出现一个轮的图片
            # datejs 日期处理js
            # jQuery库,这是经典库了 http://t.mb5u.com/jquery/   1.8.3
            # jquery.blockUI 提示窗口
            # jquery.hotkeys 键盘js处理
            # jquery.placeholder 实现文本框显示描述文字
            # jquery.timeago 时间格式
            # jquery.form 表单处理
            # jquery.ba-bbq
            # underscore库,弥补了jQuery没有实现的地方 文档http://www.css88.com/doc/underscore1.6.0/
              所有的功能都封装在名为"_"命名空间内
              常用_.each()来代替javascript中的循环
              _.range()产生一个范围的数列
              function sumTotal(){
                var x=0;
                _.each(_.range(1,101),function(i){
                    x+=i;
                });
                console.log("Result",x);
              }
             
    *jQuery 简单操作
        #选择器
          @ $("input") 选择特定的HTML元素
          @ $("#content") 选择指定的id的HTML元素
          @ $(".title") 选择明确的css样式类的所有元素
          @ $("span.title") 组合选择元素,可以更精确选择元素
         
        # 事件
          @ $("button").click(function){
                console.log("someone clicked on the button")
            }); // 按钮上的单点事件
           
        # 修改DOM
          @ $(".main_content").html('<div style="color:white">Hello world!' </div>) <!--替换内容-->
          @ $(".main_content").append('<div style="color:white">Hello world again!' </div>) <!--追加内容到后面-->
          @ $(".main_content").prepend('<div style="color:white">Hello world front!' </div>) <!--追加内容到前面-->
          放文本用 text()
          $(".main_content").text('The <div> element will appear as-is in the browser.');
         
        # 异步调用
           服务端:
                @app.route('/service_plus', methods=["POST"])
                def service_plus():
                    data = flask.request.json
                    a = data["a"]
                    b = data["b"]
                    delay = data.get("delay", 0)
                    time.sleep(delay)
                    return flask.jsonify(**{
                        "addition": a + b,
                    })
                   
            客户端:
                $.ajax("/service_plus", {
                    type: "POST",
                    dataType: "json",
                    data: JSON.stringify({
                    "a": 3,
                    "b": 5,
                    }),
                    contentType: "application/json",
                }).then(function(a) {
                    console.log("3+5=", a.addition);
                });
               
            说明:
                @ JSON.stringify  把字典转换为json
                @ flask.jsonify 返回json串
               
                在所有的处理异步操作中,总是返回一个deferred
                function func1() {
                    var def1 = $.ajax(...); // A first call to the server.
                    var def2 = $.ajax(...); // A second call.
                    var def3 = $.when(def1, def2); // We multiplex all that.
                    var def4 = def3.then(...); // Some more complexity: we chain it.
                    // Now we don't forget to return a deferred that represents the complete
                    operation.
                    return def4;
                    };
                    function func2() {
                        var def = func1(); // We want to call func1().
                        // Now if I need to know when func1() has finished all its operations I h
                        ave a deferred that represents that.
                        var def2 = def.then(...);
                        // And finally we don't forget to return a deferred because func2() is, b
                        y transitivity, a function
                        // that performs an asynchronous call. So it should return a deferred too.
                        return def2;
                        };           
          
             
    *模块定义
        (function() {
            app = {};
            function main() {
                console.log("launch application");
            };
            app.main = main;
        })();   
        采用匿名函数封装
               
           
    * 例子
        function openerp_picking_widgets(instance){

        var module = instance.stock;
        var _t     = instance.web._t;
        var _lt = instance.web._lt;
        var QWeb   = instance.web.qweb;

        // This widget makes sure that the scaling is disabled on mobile devices.
        // Widgets that want to display fullscreen on mobile phone need to extend this
        // widget.

        module.MobileWidget = instance.web.Widget.extend({
            start: function(){
                if(!$('#oe-mobilewidget-viewport').length){
                    $('head').append('<meta id="oe-mobilewidget-viewport" name="viewport" content="initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">');
                }
                return this._super();
            },
            destroy: function(){
                $('#oe-mobilewidget-viewport').remove();
                return this._super();
            },
        });
       
        #var _t     = instance.web._t; 翻译
       
       
    * 采用异步 做 (a+b)*(c+d) 这个功能 ,这是例子,主要参考模式思想
        (function(){
            app = {};
           
            function main(){
                $("button").click(function(){
                    plusmultplus(1,2,3,4).then(function(result){
                        console.log("(1+2)*(3+4)=",result.multiplication);
                    });
                });
            }
           
            app.main = main;
           
            function plusmultplus(a,b,c,d){
                var def1 = $.ajax("/service_plus",{
                    type:"POST",
                    dataType:"json",
                    data:JSON.stringify({
                        "a":a,
                        "b":b,
                    }),
                    contentType:"application/json",
                });
               
                var def2 = $.ajax("/service_plus",{
                    type:"POST",
                    dataType:"json",
                    data:JSON.stringify({
                        "c":c,
                        "d":d,
                    }),
                    contentType:"application/json",
                });
               
                return $.when(def1,def2).then(function(result1,result2){
                    return $.ajax("/service_mult",{
                        type:"POST",
                        dataType:"json",
                        data:JSON.stringify({
                            "a":result1[0].addition,
                            "b":result2[0].addition,
                        }),
                        contentType:"application/json",
                    });
                });
            }
           
           
           
        })();
       
        --------------------------------
        @app.route('/service_plus', methods=["POST"])
        def service_plus():
            data = flask.request.json
            a = data["a"]
            b = data["b"]
            delay = data.get("delay", 0)
            time.sleep(delay)
            return flask.jsonify(**{
                "addition": a + b,
            })
       
        @app.route('/service_mult', methods=["POST"])
        def service_mult():
            data = flask.request.json
            a = data["a"]
            b = data["b"]
            delay = data.get("delay", 0)
            time.sleep(delay)
            return flask.jsonify(**{
                "multiplication": a * b,
            })
       
    * Web Framework 构造图形化的javascript 应用
        # 基础框架js所在位置 addons/web/static/src/js/openerpframework
        #js 在odoo中的运用
            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() {
                        console.log("pet store home page loaded");
                    },
                });
               
                instance.web.client_actions.add('petstore.homepage', 'instance.oepetstore.HomePage');
            }
           
            @ odoo运行时会把所有的javascript文件连接为一个文件,然后压缩,若要调试,必须采用debug模式
            @ 上面创建了, oepetstore 模块,且做为属性放在全局变量openerp中;模块名和addon的模块名要一
               致,否则不能运行
            @ 当载入addon这个模块时,该js模块调用,传入instance参数,这个参数代表当前 OpenERP 的 Web 客户端实例,
               包含了所有相关当前会话数据, 以及所有 Web 模块的变量 
            @ instance.oepetstore = {}; 这是命名空间,用来声明我们模块内自己使用的所有类和变量
           
        # js在odoo定义一个新类
            instance.oepetstore.MyClass = instance.web.Class.extend({
                say_hello: function(){
                    console.log("hello");
                }
            });
           
            @ 调用instance.web.Class.extend() 传入一个dictionary 参数
            @ 在方法内,用this访问属性值
                instance.oepetstore.MyClass = instance.web.Class.extend({
                    say_hello: function() {
                        console.log("hello", this.name);
                    },
                });
                var my_object = new instance.oepetstore.MyClass();
                my_object.name = "Nicolas";
                my_object.say_hello();
               
            @ 类可以有一个构造函数 init()
                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();
               
            @ 重载方法时,使用 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();
                               
                   
    * Widgets
        # 第一个部件
        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');
        这句是把这个部件注册为客户端的action
        @ start 这个方法部件初始化会自动调用
        @ 改造一下用上jQuery 的$el
        instance.oepetstore.HomePage = instance.web.Widget.extend({
            start: function() {
                this.$el.append("<div>Hello dear OpenERP user!</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);
                },
            });   

            显示结果:
            <div class="oe_petstore_homepage">
                <div>Hello dear OpenERP user!</div>
                <div class="oe_petstore_greetings">
                    <div>We are so happy to see you again in this menu!</div>
                </div>
            </div>
           
            @ new instance.oepetstore.GreetingsWidget(this); 实例化部件
              this 参数,在这里代表 HomePage实例,部件有父子关系
              instance.oepetstore.GreetingsWidget = instance.web.Widget.extend({
                start: function() {
                    console.log(this.getParent().$el );
                    // will print "div.oe_petstore_homepage" in the console
                },
              });   
              ----------
             instance.oepetstore.HomePage = instance.web.Widget.extend({
                start: function() {
                    var greeting = new instance.oepetstore.GreetingsWidget(this);
                    greeting.appendTo(this.$el);
                    console.log(this.getChildren()[0].$el);
                    // will print "div.oe_petstore_greetings" in the console
                },
                });
            @ 当重载部件的init()时,必须以父部件作为第一参数传入,并调用传入给 this._super()
                instance.oepetstore.GreetingsWidget = instance.web.Widget.extend({
                    init: function(parent, name) {
                        this._super(parent);
                        this.name = name;
                    },
                });
                当一个部件没有父部件时,实例化传null参数
               
        # 销毁部件
            greeting.destory()
           
        # 事件
            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() {
                        self.trigger("user_choose", true);
                    });
                    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);
                    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");
                    }
                },
            });   

            @ this 隐式传入到所有的函数,每个已声明的函数都有自己的 this 。
              所以,当我们在一个函数内声明了另一个函数,这个新功能将有自己的 this ,
              这和父函数 this 含义不同,采用了 var self = this; 保存
            @ self.trigger("user_choose", true); 定义user_choose为名事件的触发器
              Widget.trigger(event_name [, ...]) 方法的第一个参数是待触发的事件名,
              也接受任何数量的其他参数。这些参数将被传递到所有的事件侦听器
            @ widget.on("user_choose", this, this.user_choose); 监听user_choose 事件
              Widget.on(event_name, object, func) 允许绑定一个事件 event_name 触发时调
              用的函数 func 。 如果 func) 是个方法,则 object 是 func) 函数的引用关联
              对象。 当 func) 被调用时, trigger() 的其他参数会传递给它
             
        # 属性   
           和普通对象属性一样,但多了一个功能,会触发事件
            start: function() {
                this.widget = ...
                this.widget.on("change:name", this, this.name_changed);
                this.widget.set("name", "Nicolas");
            },
            name_changed: function() {
                console.log("The new value of the property 'name' is", this.widget.get("name"));
            }
           
            @ Widget.set(name, value) 方法设置某个属性的值。如果该值改变(或以前没有
              值) , 对象将触发一个事件 change:xxx : xxx 是属性名称。
              Widget.get(name) 读取属性值。
             
        # 部件辅助工具
           选择器  this.$el.find("input.my_input") <=> this.$("input.my_input")   
           要分析jQuery事件和部件事件
           简化jQuery事件写法
            start: function() {
                var self = this;
                this.$(".my_button").click(function() {
                    self.button_clicked();
                });
            }
            --------
            events: {
                "click .my_button": "button_clicked",
            },
          
          
        # 翻译
          记得js源码有两行
            var _t = instance.web._t,
                _lt = instance.web._lt;
            这是导入翻译功能
            this.$el.text(_t("Hello dear user!"));
            和对应python代码中 _() 翻译
            _lt()返回一个函数
            var text_func = _lt("Hello dear user!");
            this.$el.text(text_func());
               

        class openerp.Widget()
        是所有可视化组件的基础类
       
        # DOM Root
            Widget() 得到DOM Root
            openerp.Widget.el  Root
            openerp.Widget.$el  jQuery打包
            openerp.Widget.template 生成Root
            openerp.Widget.tagName  生成元素 默认是div
            openerp.Widget.id  生成Root的id属性
            openerp.Widget.className
            openerp.Widget.renderElement() 渲染是生成Root
           
        # 使用widget
            openerp.Widget.init(parent)
            加元素
            openerp.Widget.appendTo(element) 加到后面
            openerp.Widget.prependTo(element) 加到前面
            openerp.Widget.insertAfter(element) 插在元素的后面
            openerp.Widget.insertBefore(element) 插在元素的前面
           
            openerp.Widget.destory()清理
            openerp.Widget.alive(deferred[, reject=false]) 状态操作
            openerp.Widget.isDestroyed() 检测有没有销毁
           
        # 访问DOM内容
            openerp.Widget.$(selector)
            this.$(selector)
            this.$el.find(selector)
           
        # 重设DOM Root
            openerp.Widget.setElement(element)
               element 可以是元素,也可以jQuery对象
              
        # DOM事件处理
            openerp.Widget.events
            如
            events:{
                'click p.oe_some_class a':'some_method',
                'change input':function(e){
                   e.stopPropagation()
                }
           
            }
            openerp.Widget.delegateEvents() 代理绑定到DOM上面
            openerp.Widget.undelegateEvents() 解绑
           
        # 子类Widget
            通过extend
            var MyWidget = openerp.Widget.extend({
            // QWeb template to use when rendering the object
            template: "MyQWebTemplate",
            events: {
                // events binding example
                'click .my-button': 'handle_click',
            },

            init: function(parent) {
                this._super(parent);
                // insert code to execute before rendering, for object
                // initialization
            },
            start: function() {
                var sup = this._super();
                // post-rendering initialization code, at this point

                // allows multiplexing deferred objects
                return $.when(
                    // propagate asynchronous signal from parent class
                    sup,
                    // return own's asynchronous signal
                    this.rpc(/* … */))
             }
            });
           
            // Create the instance
            var my_widget = new MyWidget(this);
            // Render and insert into DOM
            my_widget.appendTo(".some-div");
           
            my_widget.destroy();
           
        # 开发指南
            @ 尽量少用id ,万一要用id 要用 _.uniqueId() 生成
                this.id=_.uniqueId()
               
            @ 尽量少用普通css名字 如 content navigator
            @ 尽量少用全局选择器  用 Widget.$el 或 Widget.$()
            @ 所有的组件都要继承 Widget()
            @ 要用QWeb进行HTML模板和渲染
           
           
    * QWeb
        instance.web.Widget 特别支持 QWeb
        <?xml version="1.0" encoding="UTF-8"?>
        <templates xml:space="preserve">
            <t t-name="HomePageTemplate">
                <div style="background-color: red;">This is some simple HTML</div>
            </t>
        </templates>
        前面js源码,有 var QWeb = instance.web.qweb; 这样可以用QWeb功能了
        instance.oepetstore.HomePage = instance.web.Widget.extend({
            start: function() {
                this.$el.append(QWeb.render("HomePageTemplate"));
            },
        });
        @ 渲染了 HomePageTemplate 模板
        @ 也可以采用集成方式
            instance.oepetstore.HomePage = instance.web.Widget.extend({
                template: "HomePageTemplate",
                start: function() {
                   
                },
            });
            发生在start方法之前,会用模板的根标签替换部件的默认根标签
       
        # 传递参数
           <t t-name="HomePageTemplate">
            <div>Hello <t t-esc="name"/></div>
        </t>
        ------
        QWeb.render("HomePageTemplate", {name: "Nicolas"});
       
        当采用集成式,要用变量 widget
        <t t-name="HomePageTemplate">
            <div>Hello <t t-esc="widget.name"/></div>
        </t>
        --------
        instance.oepetstore.HomePage = instance.web.Widget.extend({
            template: "HomePageTemplate",
            init: function(parent) {
                this._super(parent);
                this.name = "Nicolas";
            },
            start: function() {
            },
        });
       
        # 模板基础 https://doc.odoo.com/trunk/web/qweb/
        <templates>
            <t t-name="HomePageTemplate">
            <div>This is some simple HTML</div>
            </t>
        </templates>
        @ <templates> 模板的根元素
        前缀 t-
            @ t-name 标识模板, QWeb.render() 可以调用指定模板
            @ t-esc 在HTML中放置文本 会转义html标签
            @ t-raw 保持原有内容输出
            @ t-if  条件语句
                <t t-if="true==true">
                    true is true
                </t>
           
            @ t-foreach  t-as 循环
                <t t-foreach="names" t-as="name">
                    <div>
                        Hello <t t-esc="name" />
                    </div>
                </t>
            @ t-att-xx 设置属性值
       
    * 部件调用数据
        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.CompoundConte
                xt()}).then(function(result) {
                    self.$el.append("<div>Hello " + result["hello"] + "</div>");
                // will show "Hello world" to the user
                });
            },
        });
       
        #连接模型用 instance.web.Model
        #采用model.call()来调用数据 call(name, args, kwargs) 是 Model 的方法
          args 是对象方法的参数列表
          kwargs 命名参数列表,这里只传了context
        # 模型中的方法始终有一个参数 context , context 是一个包含多个key的dictonary
        # CompoundContext 这个类用来传递用户上下文(语言,时区等..) 给服务器的
          其构造函数的参数是任意数量的 dictionary
         
    * 部件较好的例子           
        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);
                        });
                    });
                },
            });
        }
        ----------------
        <?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>
       
        .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;
        }

    ====================

    * RPC
        采用异步的方式来调用
        #高级API
          访问对象方法用 openerp.Module
          映射服务端对象用 call() 和 query()
            var Users = new openerp.Model('res.users');

                Users.call('change_password', ['oldpassword', 'newpassword'],
                                  {context: some_context}).then(function (result) {
                    // do something with change_password result
                });
          query()是 search+read 在后端操作
            Users.query(['name', 'login', 'user_email', 'signature'])
                 .filter([['active', '=', true], ['company_id', '=', main_company]])
                 .limit(15)
                 .all().then(function (users) {
                // do work with users records
            });
                     
          openerp.Model.call(method[, args][, kwargs])
            method 是rpc的方法名
            args 传入方法的参数
            kwargs 关键词参数
           
          openerp.Model.query(fields)
            fields 字段列表
          first() 取第一个记录
           
         class openerp.web.Query(fields)类下方法
            openerp.web.Query.all() 得到上面query() 集的所有
            openerp.web.Query.first() 要第一条,没有就是null
            openerp.web.Query.count() 得到的记录总数
            openerp.web.Query.group_by(grouping...) 分组来列表
            openerp.web.Query.context(ctx) 添加上下文
            openerp.web.Query.filter(domain) 条件过滤domain表达式
            opeenrp.web.Query.offset(offset) 设定起点
            openerp.web.Query.limit(limit) 设定要返回的数量
            openerp.web.Query.order_by(fields…)  记录排序
           
        #聚合
            some_query.group_by(['field1', 'field2']).then(function (groups) {
                // do things with the fetched groups
            })
           
            openerp.web.QueryGroup.get(key)
            得到key的值,key可以为:
                @ grouped_on
                @ value
                @ length
                @ aggregates
               
            openerp.web.QueryGroup.query([fields...]) 等价于
            openerp.web.Model.query()
           
            openerp.web.QueryGroup.subgroups()
           
        #低级API RPC访问python
            opeenrp.session()
            如:
            openerp.session.rpc('/web/dataset/resequence', {
                model: some_model,
                ids: array_of_ids,
                offset: 42
            }).then(function (result) {
                // resequence didn't error out
            }, function () {
                // an error occured during during call
            });
    ========================
    * Web 客户端
        写测试用例
        # 断言
            ok(state[, message])
            strictEqual(actual, expected[, message]) 相当于 ok(actual === expected, message))
            notStrictEqual(actual, expected[, message]) 相当于 ok(actual !== expected, message))
            deepEqual(actual, expected[, message])
            notDeepEqual(actual, expected[, message])
            throws(block[, expected][, message]) 抛出异常
            equal(actual, expected[, message]) 宽松相等
            notEqual(actual, expected[, message])
           
            示例:
            {
                'name': "Demonstration of web/javascript tests",
                'category': 'Hidden',
                'depends': ['web'],
                'js': ['static/src/js/demo.js'],
                'test': ['static/test/demo.js'],
            }
            // src/js/demo.js
            openerp.web_tests_demo = function (instance) {
                instance.web_tests_demo = {
                    value_true: true,
                    SomeType: instance.web.Class.extend({
                        init: function (value) {
                            this.value = value;
                        }
                    })
                };
            };

            // test/demo.js
            test('module content', function (instance) {
                ok(instance.web_tests_demo.value_true, "should have a true value");
                var type_instance = new instance.web_tests_demo.SomeType(42);
                strictEqual(type_instance.value, 42, "should have provided value");
            });
           
    * 显示图片
      <img class="oe_kanban_image" src ="data:image/png; base64,${replace this by base64}" />
     
    * Web Components (Action manager)
        # 看一列子:
        <record model="ir.actions.act_window" id="message_of_the_day_action">
            <field name="name">Message of the day</field>
            <field name="res_model">message_of_the_day</field>
            <field name="view_type">form</field>
            <field name="view_mode">tree,form</field>
        </record>
        <menuitem id="message_day" name="Message of the day" parent="petstore_menu"
        action="message_of_the_day_action"/>
       
        对应下的js 处理,没人xml快捷,但用js更灵活
        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().the
                n(function(result) {
                    _.each(result, function(item) {
                        var $item = $(QWeb.render("PetToy", {item: item}));
                        self.$el.append($item);
                        $item.click(function() {
                            self.item_clicked(item);
                        });
                    });
                });
            },
            item_clicked: function(item) {
                this.do_action({
                type: 'ir.actions.act_window',
                res_model: "product.product",
                res_id: item.id,
                views: [[false, 'form']],
                target: 'current',
                context: {},
                });
            },
            });
           
        #上面是窗体Action 下面看焉 client Action
            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');
       
            @ instance.web.client_actions 是一个 Registry类的实例
              要打开关键字是petstore.home的action ,就实例化instance.oepetstore.HomePage
            @对应的菜单
                <record id="action_home_page" model="ir.actions.client">
                  <field name="tag">petstore.homepage</field>
                </record>       
             <menuitem id="home_page_petstore_menu" name="Home Page" parent="petstore_menu"
                 action="action_home_page"/>

  • 相关阅读:
    一般操作
    node express mongodb 数据录入
    express新版本后app.use(express.bodyParser())无效
    npm adduser报错问题
    01demo-mongodb
    Win32汇编--02必须了解的基础知识
    第17章 本书最后将学习什么呢(需要回头学习)
    第十六章 直接定址表(需要回头学)
    指令系统总结
    第十五章 外中断
  • 原文地址:https://www.cnblogs.com/toby2chen/p/5177153.html
Copyright © 2020-2023  润新知