欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Odoo

程序员文章站 2024-03-23 23:58:52
...

原贴地址: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模块安装的时候,产品分类条将字段**。