Odoo

原贴地址:https://www.odoo.com/documentation/10.0/howtos/website.html

声明:这篇指导假设你有python的知识并安装了Odoo,请注意文件的目录结构,本文的目录结构与原文不同。

创建一个基础模块

在Odoo中,工作是通过创建的模型展开的。

模型决定了Odoo的行为。也许是通过添加新的行为,亦或许是通过已经存在的(通过其他模型安装的行为)

Odoo的scaffold能够初始化一个基础模块。是你可以快速的开始。

$ ./odoo-bin scaffold Academy my-modules
     
     

这将自动创建my-modules模块目录,目录里面有一个academy。如果你愿意,这个目录可以是一个存在的目录,但是子目录的名字必须的惟一的。

一个样例

我们有一个安装好的模块,尽管他并不能做什么:

1.打开Odoo的服务器,用下面的方式

$ ./odoo-bin --addons-path addons,my-modules

--addon-path是包含模块的路径。addons是必须包含的,里面有启动文件,my-modules是我们刚才安装的。

2.浏览器进入http://localhost:8069

3.进入Settings-Modules-Modules

4.在右上角删除过滤器(应该说的是搜索框里的api x)并搜索academy

5.点击academy模块的安装按钮

这个过程大家应该很熟悉了,很多地方都讲过,他说的有点复杂,我在多说一点,如果没有发现模块,打开开发模式,然后切回到setting(应用)页面,左边有更新应用列表。

浏览器

控制器终端浏览器请求并返回数据。

#添加一个简单的控制器并确保他被引入__init__.py(这样Odoo才能找到他)

academy/controllers/controllers.py


     
     
  1. # -*- coding: utf-8 -*-
  2. from odoo import http
  3. class Academy(http.Controller):
  4. @http.route('/academy/academy/', auth='public')
  5. def index(self, **kw):
  6. return "Hello, world"
  7. # @http.route('/academy/academy/objects/', auth='public')
  8. # def list(self, **kw):

这里我怀疑是新旧版本的问题,作为初学者,我还是愿意遵循他创建文件夹的结构,把这个东西写在controller文件夹里。

重启服务器ctrl+c两次。

在浏览器里输入localhost:8069/academy/academy/

hello,world!

模板

用python生成HTML并不是很理想。

一般的解决方案是模板。pseudo-documents有占位符和展示逻辑: Odoo允许任何Python模板系统,但是提供他自己的QWeb模板系统,整合了他自己的特点。

创建一个模板并确保模板文件在__manifest__.py中注册(如果写在了),并转换控制器使用我们的模板。

academy/controllers/controllers.py


     
     
  1. class Academy(http.Controller):
  2. @http.route('/academy/academy/', auth='public')
  3. def index(self, **kw):
  4. return http.request.render( 'academy.index', {
  5. 'teachers': [ "C"],
  6. })
  7. # @http.route('/academy/academy/objects/', auth='public')
  8. # def list(self, **kw):

academy/views/templates.xml


     
     
  1. <odoo>
  2. <data>
  3. <template id="index">
  4. <title>Academy </title>
  5. <t t-foreach="teachers" t-as="teacher">
  6. <p> <t t-esc="teacher"/> </p>
  7. </t>
  8. </template>
  9. <!-- <template id="object"> -->
  10. <!-- <h1><t t-esc="object.display_name"/></h1> -->
  11. <!-- <dl> -->

这个模板中有一个迭代器(t-foreach)遍历了所有的teachers(通过模板的上下文(这里就是controller))。

最终重启Odoo并升级模块数据。

Odoo能够重启并同时创建模块。

在浏览器里输入localhost:8069/academy/academy/

Dinana Padilla

Jody Caaoll

Lester Yaughn


在Odoo上存储数据

Odoo的模型映射数据库

在之前的部分我们只是用python的代码展示了一个字符串列表。这并不允许改变或维持贮存,所以我们要将他存入数据库。

定义数据模型

定义一个teacher模型,并确保他被__init__.py(models内的)引入,并正确加载。

academy/models/models.py


     
     
  1. from odoo import models, fields, api
  2. class Teachers(models.Model):
  3. _name = 'academy.teachers'
  4. name = fields.Char()

接着为模型安装基础的访问控制,并添加他们的manifest:

academy/__manifest__.py


     
     
  1.      # always loaded
  2. 'data': [
  3. 'security/ir.model.access.csv',
  4. 'templates.xml',
  5. ],
  6. # only loaded in demonstration mode

academy/security/ir.model.acess.csv


     
     
  1. id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
  2. access_academy_teachers,access_academy_teachers,model_academy_teachers,, 1, 0, 0, 0

这里简单的给了所有用户(group_id:id)读权限(perm_read)

数据文件(XML或者CSV)必须被添加在模块的manifest中,Python文件(模型或者控制器)不用,但是Python文件必须引入在__init__.py中(直接或者间接)

管理员用户通过权限来控制,他们能进入所哟逇模型甚至没有给权限的

数据样例

第二步是为系统添加一些数据样例,这样测试起来很容易。通过添加demo数据可以很容做到。demo.xml也必须链接到manifest:

academy/demo/demo.xml


     
     
  1. <odoo>
  2. <data>
  3. <record id= "padilla" model= "academy.teachers">
  4. <field name= "name">Diana Padilla</field>
  5. </record>
  6. <record id= "carroll" model= "academy.teachers">
  7. <field name= "name">Jody Carroll</field>
  8. </record>
  9. <record id= "vaughn" model= "academy.teachers">
  10. <field name= "name">Lester Vaughn</field>
  11. </record>
  12. </data>
  13. </odoo>

数据文件可用于演示和非演示数据。演示数据只在演示模式被加载,可以用作测试和演示,非演示数据总是被加载,并在系统初始化的时候就启用了。

在这种情况下我们使用演示数据,因为一个系统的真实的用户会想要输入或导出他们自己的教师列表,而这个列表只用于测试。

访问数据

最后一步就是改变模型和模板来使用我们的演示数据。

1.从数据库获取记录来替代掉已经存在的静态的列表

2.由于search()返回一个记录的集合,匹配过滤器("所有的记录"在合理),改变模板或者打印每一个教师的name

academy/controllers/controllers.py


     
     
  1. class Academy(http.Controller):
  2. @http.route('/academy/academy/', auth='public')
  3. def index(self, **kw):
  4. Teachers = http.request.env[ 'academy.teachers']
  5. return http.request.render( 'academy.index', {
  6. 'teachers': Teachers.search([])
  7. })
  8. # @http.route('/academy/academy/objects/', auth='public')

academy/views/template.xml


     
     
  1. <template id="index">
  2. <title>Academy </title>
  3. <t t-foreach="teachers" t-as="teacher">
  4. <p> <t t-esc="teacher.id"/> <t t-esc="teacher.name"/> </p>
  5. </t>
  6. </template>
  7. <!-- <template id="object"> -->

重启服务器并更新模块(为了更新manifest和模板,并加载演示数据),接着去http://localhost:8069/academy/academy/。页面将会有些不同:名字被加上数字前缀(数据库对教师的识别)。

看起来名字没有变化,我虽然不知道数据是什么时候进去的,但是这次名字确实是从数据库取出来的。如果没有,卸载模块重新安装。


网站支持

Odoo绑定一个模块专注于建站。

目前为止我们直接使用了控制器,但是Odoo8添加了更深层的继承和一个其他服务。(比如,默认样式,主题)用过网站模块。

1.添加website作为academy的依赖

academy/__manifest__.py


     
     
  1. 'version': '0.1',
  2. # any module necessary for this one to work correctly
  3. 'depends': [ 'website'],
  4. # always loaded
  5. 'data': [

2.在控制器中添加website=True标记,在请求对象时这里添加了一些新的变量并允许使用网络布局。

academy/controllers/controllers.py


     
     
  1. from odoo import http
  2. class Academy(http.Controller):
  3. @http.route('/academy/academy/', auth='public', website=True)
  4. def index(self, **kw):
  5. Teachers = http.request.env[ 'academy.teachers']
  6. return http.request.render( 'academy.index', {

3.在模板中使用网络布局

academy/views/template.xml


     
     
  1. <odoo>
  2. <data>
  3. <template id= "index">
  4. <t t-call= "website.layout">
  5. <t t-set= "title">Academy</t>
  6. <div class="oe_structure">
  7. <div class="container">
  8. <t t-foreach="teachers" t-as="teacher">
  9. <p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>
  10. </t>
  11. </div>
  12. </div>
  13. </t>
  14. </template>
  15. <!-- <template id="object"> -->

在重启服务器升级模块以后(为了更新manifest和模板)访问http://localhost:8069/academy/academy 你会得到一个看起来更舒服的页面,有标题logo和一些内置页面元素(menu,footer)

图我就不贴了,比教程贴的那个好看多了。

这个网站的布局同样提供支持:点击登录(右上角),填充凭证(admin/admin默认)来登录。(我的已经是登录状态了)

你现在在Odoo的后台:管理员特有界面。现在点击网站menu里的元素(左上角)

我们回到网站,作为一个管理员,我们能访问网站提供的高级编辑特征:

1.模板代码编辑(Customize-HTML Editor)你可以看见当前页面使用的所有的模板。

2.编辑按钮在左上角,装换位编辑模式,这样富文本编辑器就可以用了。

3.大量的其他特性比如移动端或者SEO

这块自己摸索下吧,介绍的应该是8,我用的11,不太一样

URL和路由

控制器方法通过route()装饰器把路由联系在一起,route()装饰器包含一个字符串和多个定制行为或者安全的属性。

我们看到的字符串就是URL,然而路由的字符串能使用转换样式匹配其中一小部分,匹配URL和和那些可用的变量,比如我们创建一个新的控制器方法来设置部分的路径并打印他。

academy/controllers/controllers.py


     
     
  1. 'teachers': Teachers.search([])
  2. })
  3. @http.route('/academy/<name>/', auth='public', website=True)
  4. def teacher(self, name):
  5. return '<h1>{}</h1>'.format(name)
  6. # @http.route('/academy/academy/objects/', auth='public')
  7. # def list(self, **kw):
  8. # return http.request.render('academy.listing', {

重启Odoo,分别访问http://localhost:8069/academy/Alics和http://localhost:8069/academy/Bob/来查看不同。

顾名思义,转换样式并不只是做提取,他们同样做验证和转换,所以我们可以换个新的控制器只接收整型数据:

academy/controllers/controllers.py


     
     
  1. 'teachers': Teachers.search([])
  2. })
  3. @http.route('/academy/<int:id>/', auth='public', website=True)
  4. def teacher(self, id):
  5. return '<h1>{} ({})</h1>'.format(id, type(id).__name__)
  6. # @http.route('/academy/academy/objects/', auth='public')

重启Odoo,访问http://localhost:8069/academy/2,就明确了为什么之前是字符串而现在是数字,再尝试下http://localhost:8069/academy/Carol,你会发现页面找不到了,因为Carol不是个整数,路由忽略了它,并且没有路由能被找到。

Odoo提供了一个添加转换器叫做model,当你给定id的时候他能直接转换为记录。容我们用他来为教师传记创建页面吧。

academy/controllers/controllers.py


     
     
  1. 'teachers': Teachers.search([])
  2. })
  3. @http.route('/academy/<model("academy.teachers"):teacher>/', auth='public', website=True)
  4. def teacher(self, teacher):
  5. return http.request.render( 'academy.biography', {
  6. 'person': teacher
  7. })
  8. # @http.route('/academy/academy/objects/', auth='public')

academy/views/templates.xml


     
     
  1. </div>
  2. </t>
  3. </template>
  4. <template id="biography">
  5. <t t-call="website.layout">
  6. <t t-set="title">Academy </t>
  7. <div class="oe_structure"/>
  8. <div class="oe_structure">
  9. <div class="container">
  10. <p> <t t-esc="person.id"/> <t t-esc="person.name"/> </p>
  11. </div>
  12. </div>
  13. <div class="oe_structure"/>
  14. </t>
  15. </template>
  16. <!-- <template id="object"> -->
  17. <!-- <h1><t t-esc="object.display_name"/></h1> -->
  18. <!-- <dl> -->

接着改变模型的列表来链接新的控制器。

这里,通过http://localhost:8069/academy/jody-carroll-2/访问新的页面。

academy/views/templates.xml

     
     
  1. <div class="oe_structure">
  2. <div class="container">
  3. <t t-foreach="teachers" t-as="teacher">
  4. <p> <a t-attf-href="/academy/{{ slug(teacher) }}">
  5. <t t-esc="teacher.name"/> </a>
  6. </p>
  7. </t>
  8. </div>
  9. </div>

     
     
  1. <div class="oe_structure"/>
  2. <div class="oe_structure">
  3. <div class="container">
  4. <h3> <t t-esc="person.name"/> </h3>
  5. </div>
  6. </div>
  7. <div class="oe_structure"/>

重启Odoo并升级模块,然后你能开到每一个教师的页面,作为一个联系,试着在一个教师的页面新建一个区域来写传记,然后去第二个,你会发现,你的传记被所有教师分享了,是因为这个区域是添加在模板里的,这个模板是被分享的。当一个页面被修改,所有的页面都将被修改。

这里做一个理解,因为我刚看的时候也没看懂如果新建一个区域,直到我翻译到后面关于t-field属性可修改这里的时候。因为我是管理员,所以网站的最上方会多一个条,条的最右边有一个Edit,点击以后进入编辑模式,t-esc属性是不可编辑的,t-field属性的可编辑是从这里编辑。

新建的一个区域是指:进入编辑模式以后,最左边的一列框,可以通过手动添加进页面的。这个区域的内容是所有同类型页面共享的。

字段编辑

数据需要被保存在指定的记录中,我们来为我们的教师添加传记字段:

academy/models/models.py


     
     
  1. _name = 'academy.teachers'
  2. name = fields.Char()
  3. biography = fields.Html()
academy/views/templates.xml

     
     
  1. <div class="oe_structure">
  2. <div class="container">
  3. <h3><t t-esc="person.name"/></h3>
  4. <div><t t-esc="person.biography"/></div>
  5. </div>
  6. </div>
  7. <div class="oe_structure"/>

重启Odoo并更新视图,重新加载教师页面,这个字段是看不见的因为他没有包含内容。

作为记录的字段,模板能使用特殊的t-field指令,这个指令允许通过字段指定接口编辑来自网站的字段内容。更改person

模板为t-field。这里注意<t>标签不支持t-field 一定会报错的。

academy/views/templates.xml


     
     
  1. <div class="oe_structure"/>
  2. <div class="oe_structure">
  3. <div class="container">
  4. <h3 t-field="person.name"/>
  5. <div t-field="person.biography"/>
  6. </div>
  7. </div>
  8. <div class="oe_structure"/>

重启Odoo并升级模块,在编辑模式下,你能看见教师的名字下方,有一个占位符和一个新的块状区域。输入的内容将会保存在相符的教师传记的biography字段中,并指向这个教师。

教师名字同样是可以编辑的,保存后,修改过的名字在第一页也是可以看见的。

t-field字段同样可以通过额外的字段格式化选项。比如我们展示了教师记录的更新日期:

academy/views/templates.xml


     
     
  1. <div class="oe_structure">
  2. <div class="container">
  3. <h3 t-field="person.name"/>
  4. <p>Last modified: <i t-field= "person.write_date"/></p>
  5. <div t-field= "person.biography"/>
  6. </div>
  7. </div>

这个展示为一个计算机的方式并且不易读,我们让他变为易读的格式:

academy/views/templates.xml


     
     
  1. <div class="oe_structure">
  2. <div class="container">
  3. <h3 t-field="person.name"/>
  4. <p>Last modified: <i t-field= "person.write_date" t-options= '{"format": "long"}'/></p>
  5. <div t-field= "person.biography"/>
  6. </div>
  7. </div>

或者这样:

academy/views/templates.xml


     
     
  1. <div class="oe_structure">
  2. <div class="container">
  3. <h3 t-field="person.name"/>
  4. <p>Last modified: <i t-field= "person.write_date" t-options= '{"widget": "relative"}'/></p>
  5. <div t-field= "person.biography"/>
  6. </div>
  7. </div>


管理和erp整合

Odoo管理端简介

Odoo管理端非常容易看到。通过网站支持部分部分。我们可以回到管理端通过导航中的Administrator-Administrator(如果登出了需要登录)

odoo的后台概念结构很简单:

1.导航,一个树结构(导航下有子导航)。导航没有子映射。。。

2.动作,动作有多种类型链接,报告,Odoo执行的代码或者数据显示。数据显示动作被称作window action,并根据视图集合告知Odoo要展示给定的模型。

3.视图有一个类型,一个与其对应的分类(列表,图形,日历),和一种模型被展示在视图里的结构。

在Odoo的管理端编辑

一般来说,一个Odoo模型本质上对用户是不可见的。想看见他必须通过动作使他生效,它本身必须可以触及,一般在导航里。

我们来在模型中创建一个导航:

academy/__manifest__.py


     
     
  1. 'data': [
  2. 'security/ir.model.access.csv',
  3. 'views/templates.xml',
  4. 'views/views.xml',
  5. ],
  6. # only loaded in demonstration mode
  7. 'demo': [

academy/views/views.xml


     
     
  1. <odoo>
  2. <record id="action_academy_teachers" model="ir.actions.act_window">
  3. <field name="name">Academy teachers </field>
  4. <field name="res_model">academy.teachers </field>
  5. </record>
  6. <menuitem sequence="0" id="menu_academy" name="Academy"/>
  7. <menuitem id="menu_academy_content" parent="menu_academy"
  8. name= "Academy Content"/>
  9. <menuitem id="menu_academy_content_teachers"
  10. parent= "menu_academy_content"
  11. action= "action_academy_teachers"/>

接着访问http://localhost:8069/web/在左上角会出现导航Academy,默认被选作第一导航,会打开教师列表。在列表中,可以创建新的教师记录,并通过记录视图转换到表单。

如果没有关于如何呈现一个记录(视图)的定义,Odoo将会自动创建一个基础的。在我看来,他适用于列表视图(只是展示教师的名字),但是在表单视图中HTML的biography字段和name字段一起被展示,并没有给出足够的空间。让我们用视图定义一个客户表单视图,来更好的展示和编辑教师的字段:

academy/views/views.xml


     
     
  1. <field name= "res_model">academy.teachers</field>
  2. </record>
  3. <record id= "academy_teacher_form" model= "ir.ui.view">
  4. <field name= "name">Academy teachers: form</field>
  5. <field name= "model">academy.teachers</field>
  6. <field name= "arch" type= "xml">
  7. <form>
  8. <sheet>
  9. <label for= "name"/> <field name= "name"/>
  10. <label for= "biography"/>
  11. <field name= "biography"/>
  12. </sheet>
  13. </form>
  14. </field>
  15. </record>
  16. <menuitem sequence= "0" id= "menu_academy" name= "Academy"/>
  17. <menuitem id= "menu_academy_content" parent= "menu_academy"
  18. name= "Academy Content"/>

模型间的关联

我们可以看到一对基础字段直接存进记录。这里有大量的基础字段。第二类字段是关系型的,用于记录间的链接(在模型中或者通过模型)。

在示例中,我们创造了courses模型,每一个课程都需要有一个teacher字段,链接一个单一的教师记录,但是一个教师可以教多门课。

academy/models/models.py


     
     
  1. name = fields.Char()
  2. biography = fields.Html()
  3. class Courses(models.Model):
  4. _name = 'academy.courses'
  5. name = fields.Char()
  6. teacher_id = fields.Many2one('academy.teachers', string="Teacher")

academy/security/ir.model.access.csv


     
     
  1. id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
  2. access_academy_teachers,access_academy_teachers,model_academy_teachers,, 1, 0, 0, 0
  3. access_academy_courses,access_academy_courses,model_academy_courses,, 1, 0, 0, 0

让我们同样添加视图,我们就可以看见和编辑课程的教师了:

academy/views/views.xml


     
     
  1. </field>
  2. </record>
  3. <record id="action_academy_courses" model="ir.actions.act_window">
  4. <field name="name">Academy courses </field>
  5. <field name="res_model">academy.courses </field>
  6. </record>
  7. <record id="academy_course_search" model="ir.ui.view">
  8. <field name="name">Academy courses: search </field>
  9. <field name="model">academy.courses </field>
  10. <field name="arch" type="xml">
  11. <search>
  12. <field name="name"/>
  13. <field name="teacher_id"/>
  14. </search>
  15. </field>
  16. </record>
  17. <record id="academy_course_list" model="ir.ui.view">
  18. <field name="name">Academy courses: list </field>
  19. <field name="model">academy.courses </field>
  20. <field name="arch" type="xml">
  21. <tree string="Courses">
  22. <field name="name"/>
  23. <field name="teacher_id"/>
  24. </tree>
  25. </field>
  26. </record>
  27. <record id="academy_course_form" model="ir.ui.view">
  28. <field name="name">Academy courses: form </field>
  29. <field name="model">academy.courses </field>
  30. <field name="arch" type="xml">
  31. <form>
  32. <sheet>
  33. <label for="name"/>
  34. <field name="name"/>
  35. <label for="teacher_id"/>
  36. <field name="teacher_id"/>
  37. </sheet>
  38. </form>
  39. </field>
  40. </record>
  41. <menuitem sequence="0" id="menu_academy" name="Academy"/>
  42. <menuitem id="menu_academy_content" parent="menu_academy"
  43. name= "Academy Content"/>
  44. <menuitem id="menu_academy_content_courses"
  45. parent= "menu_academy_content"
  46. action= "action_academy_courses"/>
  47. <menuitem id="menu_academy_content_teachers"
  48. parent= "menu_academy_content"
  49. action= "action_academy_teachers"/>

他需要在教师的页面也能直接创造新的课程,或者看到所有他要教授的课程,所以在教师模型中添加转换关系。

academy/models/models.py


     
     
  1. name = fields.Char()
  2. biography = fields.Html()
  3. course_ids = fields.One2many( 'academy.courses', 'teacher_id', string= "Courses")
  4. class Courses(models.Model):
  5. _name = 'academy.courses'

academy/views/views.xml


     
     
  1. <form>
  2. <sheet>
  3. <label for= "name"/> <field name= "name"/>
  4. <label for= "biography"/>
  5. <field name= "biography"/>
  6. <field name= "course_ids">
  7. <tree string= "Courses" editable= "bottom">
  8. <field name= "name"/>
  9. </tree>
  10. </field>
  11. </sheet>
  12. </form>
  13. </field>

讨论和通知

Odoo提供技术模型,虽然不能直接满足业务需要,但是并不需要亲手创建他们就可以扩展业务对象的能力。

其中有一个叫做Chatter的系统,拥有Odoo的email和信息系统的部分功能,能够将通知和讨论功能添加到任何模型中。模型只要继承 mail.thread,并在表单视图中添加message_ids字段来显示讨论线程。讨论线程是预记录。

对于我们的academy,允许通过讨论的方针来调整教师和助手的课程变化或者商讨。

academy/models/models.py


     
     
  1. class Courses(models.Model):
  2. _name = 'academy.courses'
  3. _inherit = 'mail.thread'
  4. name = fields.Char()
  5. teacher_id = fields.Many2one( 'academy.teachers', string= "Teacher")

academy/views/views.xml


     
     
  1. <label for="teacher_id"/>
  2. <field name="teacher_id"/>
  3. </sheet>
  4. <div class="oe_chatter">
  5. <field name="message_follower_ids" widget="mail_followers"/>
  6. <field name="message_ids" widget="mail_thread"/>
  7. </div>
  8. </form>
  9. </field>
  10. </record>

在每一个课程表格的下方,有一个讨论线程,可能为系统的用户留下信息,跟随或者不跟随的讨论链接到指定的课程。

卖课

Odoo允许提供业务模型,允许更直接的使用或者选择业务需求。比如website_sale模块,安装了一个e-commerce网站,基于Odoo系统上的产品。我们可以容易的 通过把我们的课程制作为产品,实现课程的订阅。

相比于之前传统的继承,这意味着要通过产品模型替换我们的课程模型,并扩展产品的原状(为他添加一切我们需要的东西)。

首先我们需要添加一个依赖:website_sale,所以我们有products(通过sale)和ecommerce接口:

academy/__manifest__.py


     
     
  1. 'version': '0.1',
  2. # any module necessary for this one to work correctly
  3. 'depends': [ 'website_sale'],
  4. # always loaded
  5. 'data': [

重启Odoo,升级你的模型,现在你的网站是一个商店了,排列了大量的预填充的产品(通过展示数据)。

第二部是替换课程模型通过product.template,并为课程添加行的产品分类:

academy/__manifest__.py


     
     
  1. 'security/ir.model.access.csv',
  2. 'views/templates.xml',
  3. 'views/views.xml',
  4. 'views/data.xml',
  5. ],
  6. # only loaded in demonstration mode
  7. 'demo': [

academy/views/data.xml


     
     
  1. <odoo>
  2. <record model="product.public.category" id="category_courses">
  3. <field name="name">Courses </field>
  4. <field name="parent_id" ref="website_sale.categ_others"/>
  5. </record>
  6. </odoo>

academy/views/demo.xml


     
     
  1. <field name="name">Lester Vaughn </field>
  2. </record>
  3. <record id="course0" model="product.template">
  4. <field name="name">Course 0 </field>
  5. <field name="teacher_id" ref="padilla"/>
  6. <field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
  7. <field name="website_published">True </field>
  8. <field name="list_price" type="float">0 </field>
  9. <field name="type">service </field>
  10. </record>
  11. <record id="course1" model="product.template">
  12. <field name="name">Course 1 </field>
  13. <field name="teacher_id" ref="padilla"/>
  14. <field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
  15. <field name="website_published">True </field>
  16. <field name="list_price" type="float">0 </field>
  17. <field name="type">service </field>
  18. </record>
  19. <record id="course2" model="product.template">
  20. <field name="name">Course 2 </field>
  21. <field name="teacher_id" ref="vaughn"/>
  22. <field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
  23. <field name="website_published">True </field>
  24. <field name="list_price" type="float">0 </field>
  25. <field name="type">service </field>
  26. </record>
  27. </odoo>

academy/models/models.py


     
     
  1. name = fields.Char()
  2. biography = fields.Html()
  3. course_ids = fields.One2many( 'product.template', 'teacher_id', string= "Courses")
  4. class Courses(models.Model):
  5. _inherit = 'product.template'
  6. teacher_id = fields.Many2one( 'academy.teachers', string= "Teacher")

academy/security/ir.model.access.csv


     
     
  1. id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
  2. access_academy_teachers,access_academy_teachers,model_academy_teachers,, 1, 0, 0, 0

academy/views/views.py


     
     
  1. </field>
  2. </record>
  3. <menuitem sequence="0" id="menu_academy" name="Academy"/>
  4. <menuitem id="menu_academy_content" parent="menu_academy"
  5. name= "Academy Content"/>
  6. <menuitem id="menu_academy_content_teachers"
  7. parent= "menu_academy_content"
  8. action= "action_academy_teachers"/>

随着安装,一些课程现在在商店中可以使用了,尽管你可能还需要寻找。

想要扩展一个模型的原型,继承他但是不要给他新的_name

product.template已经使用了讨论系统,所以我们可以在扩展模块中删除它

我们创建了我们的课程就像默认被展示一样,所以不需要登录你也可以看到。

注意

首先,views.py中要多删一些东西,因为我们把course类的_name删了,所以找不到academy.courses。所以views中有一大段model为academy.coursses是要注释掉的。

然后还会报错:

External ID not found in the system: %s' % xmlid
     
     

所以删掉

    <field name="parent_id" ref="website_sale.categ_others"/>
     
     

转换存在的视图

我们有一个简介要看:

新模型的创建

新视图的创建

新纪录的创建

转换存在的模型

我们要保留现有记录的改变和现有视图的改变,我们现在要在商店页面做这些。

视图的转变通过创建扩展视图完成,扩展视图被应用在原始视图上,并改变了他。这些转换的视图可以被添加也可以被删除,都不会改变原有的视图,这样会更容易的实验和回滚。

自从我们的课程免费,没有理由在商店页面展示他的加个,所以我们想要转换视图并隐藏价格(如果是0)。第一个工作是找到哪个视图展示了价格,可以通过Customize-HTML Editor来完成它。编辑器是用来读取包含给定页面中的各种的模板。通过他们中的一部分,‘产品’看起来像个罪犯。

转换视图结构分3步:

1.创建新视图

2.通过设置视图的inherit_id来改变视图扩展id的方式改变视图。

3.在结构中,从被改变的视图中使用xpath便签来选择和改变元素

academy/views/templates.xml


     
     
  1. <div class="oe_structure"/>
  2. </t>
  3. </template>
  4. <template id="product_item_hide_no_price" inherit_id="website_sale.products_item">
  5. <xpath expr="//div[hasclass('product_price')]/b" position="attributes">
  6. <attribute name="t-if">product.price > 0</attribute>
  7. </xpath>
  8. </template>
  9. <!-- <template id="object"> -->
  10. <!-- <h1><t t-esc="object.display_name"/></h1> -->
  11. <!-- <dl> -->

我们要做的第二个改变时使产品分类条默认:Customize-Product分类让我们触发一个产品分类树的开关(被用于主显示的过滤)

这部分可以通过扩展模板的customize_show和active字段完成:一个扩展模板(就像我们刚创建的一样)能够被customize_show=True。这个选择将在定制菜单中展示视图,定制菜单有个checkbox框,允许管理员激活或者关闭他们(很容易设定他们的网站页面)

我们简单的需要改变产品分类记录并设置他的默认值为active=True:

academy/views/template.xml


     
     
  1. </xpath>
  2. </template>
  3. <record id= "website_sale.products_categories" model= "ir.ui.view">
  4. <field name= "active" eval= "True"/>
  5. </record>
  6. <!-- <template id= "object"> -->
  7. <!-- <h1><t t-esc= "object.display_name"/></h1> -->
  8. <!-- <dl> -->

有了它,在academy模块安装的时候,产品分类条将字段激活。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值