Odoo的网页模块QWEB简述_第1页
Odoo的网页模块QWEB简述_第2页
Odoo的网页模块QWEB简述_第3页
Odoo的网页模块QWEB简述_第4页
Odoo的网页模块QWEB简述_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Odoo/OpenERP的网页模块QWEB简述1.web模块注意,OpenERP模块中web部分用到的所有文件必须被放置在模块内的static文件夹里。这是强制性的,出于安全考虑。事实上,我们创建的文件夹CSS,JS和XML,仅仅是一个习惯。static文件夹oepetstore/static/css/petstore.css是我们的CSS文件。oepetstore/static/xml/petstore.xml是一个XML文件,将包含我们QWeb的模板。oepetstore/static/js/petstore.js包含应用程序的JavaScript代码。像OpenERP的XML文件包含了视

2、图或数据一样,必须在_openerp_.py文件内标明这些文件。下面是我们增加的行,它告诉web client必须记载这些文件:js:static/src/js/*.js,css:static/src/css/*.css,qweb:static/src/xml/*.xml,OpenERP内,默认会把所有的JavaScript文件连接为一个文件。然后,我们执行一个叫minification的操作。minification将移除文件中的所有的注释、空格和换行符。最后,发送这个文件给用户浏览器。但这么做的缺点,是无法调试应用程序。为了避免这种副作用,仍然能够调试的解决办法是:在OpenERP的URL

3、后面添加一个参数?debug.添加后的URL:http:/localhost:8069/?debug当您使用带debug参数的URL,应用程序将不会执行串联所有minification的JavaScript文件这个过程。应用程序也将需要更多的时间来加载,但你能进行调试开发了。在前面的章节中,我们解释了JavaScript缺少命名空间机制,来分割在不同的JavaScript文件中声明的变量。并且我们提出了模块模式这个简单方法。模块模式(如app.js文件):(function()app=;functionmain()console.log(launch application);app.main

4、=main;)();在OpenERP的web框架内,有个类似于模块模式的等价物,集成了该框架的其余部分。请注意,OpenERP的Web模块与其他OpenERP的addon模块概念上是不同的,一个addon模块是一个包含很多文件的文件夹,web模块仅仅是一个有命名空间概念的JavaScript。1)模块oepetstore/static/js/petstore.js声明了这样的模块:openerp.oepetstore=function(instance)instance.oepetstore=;instance.oepetstore.XXX=.;在OpenERP的Web框架内,通过声明一个函数

5、来声明一个JavaScript模块,并把这个函数放在全局变量openerp的属性内.这个属性名称必须和OpenERP addon模块名称一致(这addon模块名为oepetstore,我应把函数赋值给openerp.oepetstore属性。如果换成openerp.petstore属性,则无法正常运行)。当Web客户端转载这个addon模块时,该函数将被调用。将传入一个名为instance的参数,这个参数代表当前OpenERP的Web客户端实例,包含了所有相关当前会话数据,以及所有Web模块的变量。在instance对象内创建与addon模块名称一致的新命名空间是个惯例。这就是为什么我们在in

6、stance.oepetstore设置一个空dictionary。这个dictionary就是命名空间,用来声明我们模块内自己使用的所有类和变量。2)类JavaScript不像其他面向对象编程语言那样有类机制。更确切地说,它提供了面向对象编程语言元素,但你必须自己定义,自己选择如何做。OpenERPWeb框架提供工具来简化这个过程,让程序员以类似其他编程语言,如Java的方式编码。定义一个新类,你需要从instance.web.Class类继承。语法如下:instance.oepetstore.MyClass=instance.web.Class.extend(say_hello:functi

7、on()console.log(hello);,);类的实例化:var my_object=new instance.oepetstore.MyClass();my_object.say_hello();类可以有一个构造函数,它方法名为init()。你可以像大多数开发语言那样,传递参数给构造器:instance.oepetstore.MyClass=instance.web.Class.extend(init:function(name)=name;,say_hello:function()console.log(hello,);,);类的继承类可以被继承i

8、nstance.oepetstore.MySpanishClass=instance.oepetstore.MyClass.extend(say_hello:function()this._super();console.log(hola,);,);varmy_object=newinstance.oepetstore.MySpanishClass(Nicolas);my_object.say_hello();this._super()不是常用的类方法3)Widgets Basics(基础部件)OpenERP中Widget部件,是一个通用组件,专门用来向用户显示内容。oepe

9、tstore实例中的petstore.js内容:openerp.oepetstore=function(instance)var_t=instance.web._t,_lt=instance.web._lt;varQWeb=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(pe

10、tstore.homepage,instance.oepetstore.HomePage);最后一行代码,把这个部件注册为客户端的action。当我们点击Pet StorePet StoreHomePage菜单项时,客户端action让部件显示出来。HomePage部件有一个start()方法。在部件初始化后,这方法被自动调用。它已接接受指令去显示其内容。我们将用它向用户显示一些内容。要做到这一点,我们使用所有部件都有的$el属性。该属性是一个jQuery对象,表示部件对应的HTML标签的根标签。部件包含了多个HTML标签,这些HTM标签有一个统一的根标签。默认情况下,部件都有一个空的根标签:

11、一个。一个HTML标签在没有具体内容的时候,是不可见的。这也解释了为什么显示instance.oepetstore.HomePage时,是个空白区域,它根本没有任何内容。要想显示些内容,我们用jQuery该对象上的一些简单方法,在根标签中添加一些HTML标签:instance.oepetstore.HomePage=instance.web.Widget.extend(start:function()this.$el.append(Hello dear OpenERP user!);,);常用方法:appendTo()方法varpettoys=newinstance.oepetstore.Pe

12、tToysList(this);/实例化PetToysList()部件pettoys.appendTo(this.$(.oe_petstore_homepage_left);/把pettoys添加到当前部件的class=.oe_petstore_homepage_left的标签中注意:newinstance.oepetstore.PetToysList(this),其中参数this,代表调用此部件的实例,表示部件的隶属关系。addClass()方法this.$el.addClass(oe_petstore_homepage);/添加样式getParent()方法用于获取父部件getChildr

13、en()方法用来获取子部件列表:this.getChildren()0.$el当你在部件中重载init()时,必须以父部件作为第一参数传入,并调用传入给this._super(),例如:instance.oepetstore.GreetingsWidget=instance.web.Widget.extend(init:function(parent,name)this._super(parent);=name;,);最后,如果一个部件没有父部件(即:在你的应用实例化时是第一个部件),传入null参数:new instance.oepetstore.GreetingsWidg

14、et(null);销毁部件:destroy()方法:当一个部件被销毁,它会先调用所有子部件的destroy()。然后,它在DOM中清楚自己。通过部件隶属关系的递归调用,避免了内存泄漏,这对容易产生内存泄露的大型JavaScript应用程序来说是非常有用的。2.Qweb在OpenERP中,使用Qweb模板引擎,专门用于Web客户端开发。Qweb是一种基于XML的模板语言,类似Genshi,Thymeleaf或Facelets。有如下几个特点:在浏览器中完全用JavaScript执行。每个模板文件(XML文件)包含了多个模板,而其他模板引擎通常做法是,模板文件和模板之间1:1的关系。在OpenER

15、P的Web的instance.web.Widget特别支持了QWeb。虽然QWeb可以用于OpenERP的Web客户端以外的地方(同时instance.web.Widget也可以不依赖于Qweb)。之所以没用用其他JavaScript模板引擎,而是选择了QWeb,是因为QWeb的扩展机制与OpenERP的视图继承机制很相似。就像OpenERP的视图一样,QWeb模版也是个XML树结构,因此很容易在模版执行XPath或DOM操作。在部件内使用QWeb首先,在文件oepetstore/static/src/xml/petstore.xml里我们定义一个简单的QWeb模板。This is some

16、simple HTML现在,修改HomePage类:varQWeb=instance.web.qweb;我们建议在所有的OpenERP web模块复制粘贴这行代码。这个对象提供访问被Web客户端加载的所有模版文件中的模版的功能。下面是我们使用XML模板文件定义的模版的例子:instance.oepetstore.HomePage=instance.web.Widget.extend(start:function()this.$el.append(QWeb.render(HomePageTemplate);,);解释:QWeb.render()方法用来渲染指定标识名称的具体模版,第一个参数就是模

17、版标识名称。另外一个常用地方是,在部件内集成Qweb:instance.oepetstore.HomePage=instance.web.Widget.extend(template:HomePageTemplate,start:function().,);当你在部件内设置类属性template时,部件就知道它需要调用QWeb.render()来呈现该模板。请注意这两个语法是有区别的。当在部件内集成Qweb时,QWeb.render()调用在部件调用start()之前发生,并用模版的根标签替换了部件的默认根标签。这会导致不同的结果,所以你应该记住它。Qweb上下文(Context)像所有的模板

18、引擎一样,Qweb模板可以包含操纵传递给模板的数据的代码。1)使用QWeb.render()的第二个参数传递数据给模版:HelloQWeb.render(HomePageTemplate,name:Nicolas);输出结果:Hello Nicolas2)当部件整合QWeb时,就不能直接传入数据了。替换办法是,模板有一个唯一变量widget,这个变量引用了当前部件:Helloinstance.oepetstore.HomePage=instance.web.Widget.extend(template:HomePageTemplate,init:function(parent)this._su

19、per(parent);=Nicolas;,start:function(),);输出结果:Hello Nicolas模版声明Qweb的语法:Qweb指令使用前缀t-的XML属性来声明新模板,我们在XML文件的根元素内添加一个元素:This is some simple HTMLEscaping转义用t-esc:在HTML中放置文本Hello这将输出变量name,并转义变量的上下文,这上下文也许是类似HTML的字符串。请注意,该属性t-esc可包含各种JavaScript表达式:输出HTML如果你明确知道变量会包含一些HTML标签,使用t-raw代替的t-esc:条件QWeb

20、的条件关键字是t-if:true is truetrue is not trueQweb条件分支没有“else”这个分支结构。循环遍历列表,使用t-foreach和t-asHello设置任意XML属性值Qweb有一个特定语法设置属性值。您必须使用t-att-xxx并用属性名替换xxx:Input your name:3.部件事件和属性1)事件部件类似现有大部分图形用户界面库(Qt,GTK,Swing,.)那样,触发事件,处理事件。例如:instance.oepetstore.ConfirmWidget=instance.web.Widget.extend(start:function()var

21、self=this;this.$el.append(Are you sure you want to perform this action?+Ok+Cancel);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.Widge

22、t.extend(start:function()varwidget=newinstance.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);elseconsole.log(The user refused to continue);,);注意:varself=this;请记住,

23、在JavaScript中,变量this会隐含传递给所有函数。如果函数像对象引用方法那么用,通过this我们知道当前的对象是什么。每个已声明的函数都有自己的this。所以,当我们在一个函数内声明了另一个函数,这个新功能将有自己的this,这和父函数this含义不同。如果我们要用原来的对象this,最简单的方法是把引用存储在一个本地变量。在OpenERP内,按照Python的习惯,通常该变量命名为self。由于这个部件应该是通用的,它本身不应执行任何具体action。所以,我们用trigger()方法设置了名字叫user_choose的触发器和事件。Widget.trigger(event_nam

24、e,.)方法的第一个参数是待触发的事件名,也接受任何数量的其他参数。这些参数将被传递到所有的事件侦听器。然后,我们修改部件HomePage去实例化一个部件ConfirmWidget,通过on()方法监听user_choose事件。Widget.on(event_name,object,func)允许绑定一个事件event_name触发时调用的函数func。如果func是个方法,则object是func函数的引用关联对象。当func被调用时,trigger()的其他参数会传递给它。例如:start:function()varwidget=.widget.on(my_event,this,this

25、.my_event_triggered);widget.trigger(my_event,1,2,3);,my_event_triggered:function(a,b,c)console.log(a,b,c);/will print1 2 32)属性属性类似与普通对象的属性。可以在对象上设置数据,但有个额外的功能:属性值改变时将触发事件。start:function()this.widget=.this.widget.on(change:name,this,_changed);this.widget.set(name,Nicolas);,name_changed:funct

26、ion()console.log(The new value of the propertynameis,this.widget.get(name);Widget.set(name,value)方法设置某个属性的值。如果该值改变(或以前没有值),对象将触发一个事件change:xxx。xxx是属性名称。4.部件辅助工具1)部件的jQeruy选择器find()方法this.$el.find(input.my_input)$()方法this.$(input.my_input)说明:我们强烈建议你也不要使用,全局jQuery函数$()。这种全局选择器满足简单应用,但在真正的大型web应用程序中不好。

27、原因很简单:当你创建一个新部件,你永远不知道它会实例化多少次。由于$()全局函数是操作浏览器中的全部HTML,如果你实例化一个部件两次,该函数会搞混两个部件的个内容。这就是为什么,大部分时间里,你在定位部件里的HTML时,必须限制jQuery选择器的选择范围。出于同样的逻辑,你也可以猜测到,不能够在部件里使用HTML id。如果widget被实例化的两次,在应用程序里将有两个相同id,但却是不同的HTML元素的情况。而这本身就是一个错误。所以,在所有的情况下,你应该坚持使用用CSS类去标记HTML标签。2)简易DOM事件绑定在前面的一部分,我们必须用click()或change()等事件绑定H

28、TML元素。现在,我们用$()来简化代码,让我们看看如何做:instance.oepetstore.MyWidget=instance.web.Widget.extend(start:function()varself=this;this.$(.my_button).click(function()self.button_clicked(););,button_clicked:function().,);还有有一个更简单的语法:instance.oepetstore.MyWidget=instance.web.Widget.extend(events:click.my_button:button_clic

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论