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
-
# -*- coding: utf-8 -*-
-
from odoo import http
-
-
class Academy(http.Controller):
-
@http.route('/academy/academy/', auth='public')
-
def index(self, **kw):
-
return "Hello, world"
-
-
# @http.route('/academy/academy/objects/', auth='public')
-
# 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
-
class Academy(http.Controller):
-
@http.route('/academy/academy/', auth='public')
-
def index(self, **kw):
-
return http.request.render('academy.index', {
-
'teachers': ["C"],
-
})
-
-
# @http.route('/academy/academy/objects/', auth='public')
-
# def list(self, **kw):
academy/views/templates.xml
-
<odoo>
-
<data>
-
<template id="index">
-
<title>Academy</title>
-
<t t-foreach="teachers" t-as="teacher">
-
<p><t t-esc="teacher"/></p>
-
</t>
-
</template>
-
<!-- <template id="object"> -->
-
<!-- <h1><t t-esc="object.display_name"/></h1> -->
-
<!-- <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
-
from odoo import models, fields, api
-
-
class Teachers(models.Model):
-
_name = 'academy.teachers'
-
-
name = fields.Char()
接着为模型安装基础的访问控制,并添加他们的manifest:
academy/__manifest__.py
-
# always loaded
-
'data': [
-
'security/ir.model.access.csv',
-
'templates.xml',
-
],
-
# only loaded in demonstration mode
academy/security/ir.model.acess.csv
-
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-
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
-
<odoo>
-
<data>
-
<record id="padilla" model="academy.teachers">
-
<field name="name">Diana Padilla</field>
-
</record>
-
<record id="carroll" model="academy.teachers">
-
<field name="name">Jody Carroll</field>
-
</record>
-
<record id="vaughn" model="academy.teachers">
-
<field name="name">Lester Vaughn</field>
-
</record>
-
</data>
-
</odoo>
数据文件可用于演示和非演示数据。演示数据只在演示模式被加载,可以用作测试和演示,非演示数据总是被加载,并在系统初始化的时候就启用了。
在这种情况下我们使用演示数据,因为一个系统的真实的用户会想要输入或导出他们自己的教师列表,而这个列表只用于测试。
访问数据
最后一步就是改变模型和模板来使用我们的演示数据。
1.从数据库获取记录来替代掉已经存在的静态的列表
2.由于search()返回一个记录的集合,匹配过滤器("所有的记录"在合理),改变模板或者打印每一个教师的name
academy/controllers/controllers.py
-
class Academy(http.Controller):
-
@http.route('/academy/academy/', auth='public')
-
def index(self, **kw):
-
Teachers = http.request.env['academy.teachers']
-
return http.request.render('academy.index', {
-
'teachers': Teachers.search([])
-
})
-
-
# @http.route('/academy/academy/objects/', auth='public')
academy/views/template.xml
-
<template id="index">
-
<title>Academy</title>
-
<t t-foreach="teachers" t-as="teacher">
-
<p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>
-
</t>
-
</template>
-
<!-- <template id="object"> -->
重启服务器并更新模块(为了更新manifest和模板,并加载演示数据),接着去http://localhost:8069/academy/academy/。页面将会有些不同:名字被加上数字前缀(数据库对教师的识别)。
看起来名字没有变化,我虽然不知道数据是什么时候进去的,但是这次名字确实是从数据库取出来的。如果没有,卸载模块重新安装。
网站支持
Odoo绑定一个模块专注于建站。
目前为止我们直接使用了控制器,但是Odoo8添加了更深层的继承和一个其他服务。(比如,默认样式,主题)用过网站模块。
1.添加website作为academy的依赖
academy/__manifest__.py
-
'version': '0.1',
-
-
# any module necessary for this one to work correctly
-
'depends': ['website'],
-
-
# always loaded
-
'data': [
2.在控制器中添加website=True标记,在请求对象时这里添加了一些新的变量并允许使用网络布局。
academy/controllers/controllers.py
-
from odoo import http
-
-
class Academy(http.Controller):
-
@http.route('/academy/academy/', auth='public', website=True)
-
def index(self, **kw):
-
Teachers = http.request.env['academy.teachers']
-
return http.request.render('academy.index', {
3.在模板中使用网络布局
academy/views/template.xml
-
<odoo>
-
<data>
-
<template id="index">
-
<t t-call="website.layout">
-
<t t-set="title">Academy</t>
-
<div class="oe_structure">
-
<div class="container">
-
<t t-foreach="teachers" t-as="teacher">
-
<p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>
-
</t>
-
</div>
-
</div>
-
</t>
-
</template>
-
<!-- <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
-
'teachers': Teachers.search([])
-
})
-
-
@http.route('/academy/<name>/', auth='public', website=True)
-
def teacher(self, name):
-
return '<h1>{}</h1>'.format(name)
-
-
-
# @http.route('/academy/academy/objects/', auth='public')
-
# def list(self, **kw):
-
# return http.request.render('academy.listing', {
重启Odoo,分别访问http://localhost:8069/academy/Alics和http://localhost:8069/academy/Bob/来查看不同。
顾名思义,转换样式并不只是做提取,他们同样做验证和转换,所以我们可以换个新的控制器只接收整型数据:
academy/controllers/controllers.py
-
'teachers': Teachers.search([])
-
})
-
-
@http.route('/academy/<int:id>/', auth='public', website=True)
-
def teacher(self, id):
-
return '<h1>{} ({})</h1>'.format(id, type(id).__name__)
-
-
-
# @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
-
'teachers': Teachers.search([])
-
})
-
-
@http.route('/academy/<model("academy.teachers"):teacher>/', auth='public', website=True)
-
def teacher(self, teacher):
-
return http.request.render('academy.biography', {
-
'person': teacher
-
})
-
-
-
# @http.route('/academy/academy/objects/', auth='public')
academy/views/templates.xml
-
</div>
-
</t>
-
</template>
-
<template id="biography">
-
<t t-call="website.layout">
-
<t t-set="title">Academy</t>
-
<div class="oe_structure"/>
-
<div class="oe_structure">
-
<div class="container">
-
<p><t t-esc="person.id"/> <t t-esc="person.name"/></p>
-
</div>
-
</div>
-
<div class="oe_structure"/>
-
</t>
-
</template>
-
<!-- <template id="object"> -->
-
<!-- <h1><t t-esc="object.display_name"/></h1> -->
-
<!-- <dl> -->
接着改变模型的列表来链接新的控制器。
这里,通过http://localhost:8069/academy/jody-carroll-2/访问新的页面。
academy/views/templates.xml
-
<div class="oe_structure">
-
<div class="container">
-
<t t-foreach="teachers" t-as="teacher">
-
<p><a t-attf-href="/academy/{{ slug(teacher) }}">
-
<t t-esc="teacher.name"/></a>
-
</p>
-
</t>
-
</div>
-
</div>
-
<div class="oe_structure"/>
-
<div class="oe_structure">
-
<div class="container">
-
<h3><t t-esc="person.name"/></h3>
-
</div>
-
</div>
-
<div class="oe_structure"/>
重启Odoo并升级模块,然后你能开到每一个教师的页面,作为一个联系,试着在一个教师的页面新建一个区域来写传记,然后去第二个,你会发现,你的传记被所有教师分享了,是因为这个区域是添加在模板里的,这个模板是被分享的。当一个页面被修改,所有的页面都将被修改。
这里做一个理解,因为我刚看的时候也没看懂如果新建一个区域,直到我翻译到后面关于t-field属性可修改这里的时候。因为我是管理员,所以网站的最上方会多一个条,条的最右边有一个Edit,点击以后进入编辑模式,t-esc属性是不可编辑的,t-field属性的可编辑是从这里编辑。
新建的一个区域是指:进入编辑模式以后,最左边的一列框,可以通过手动添加进页面的。这个区域的内容是所有同类型页面共享的。
字段编辑
数据需要被保存在指定的记录中,我们来为我们的教师添加传记字段:
academy/models/models.py
-
_name = 'academy.teachers'
-
-
name = fields.Char()
-
biography = fields.Html()
academy/views/templates.xml
-
<div class="oe_structure">
-
<div class="container">
-
<h3><t t-esc="person.name"/></h3>
-
<div><t t-esc="person.biography"/></div>
-
</div>
-
</div>
-
<div class="oe_structure"/>
重启Odoo并更新视图,重新加载教师页面,这个字段是看不见的因为他没有包含内容。
作为记录的字段,模板能使用特殊的t-field指令,这个指令允许通过字段指定接口编辑来自网站的字段内容。更改person
模板为t-field。这里注意<t>标签不支持t-field 一定会报错的。
academy/views/templates.xml
-
<div class="oe_structure"/>
-
<div class="oe_structure">
-
<div class="container">
-
<h3 t-field="person.name"/>
-
<div t-field="person.biography"/>
-
</div>
-
</div>
-
<div class="oe_structure"/>
重启Odoo并升级模块,在编辑模式下,你能看见教师的名字下方,有一个占位符和一个新的块状区域。输入的内容将会保存在相符的教师传记的biography字段中,并指向这个教师。
教师名字同样是可以编辑的,保存后,修改过的名字在第一页也是可以看见的。
t-field字段同样可以通过额外的字段格式化选项。比如我们展示了教师记录的更新日期:
academy/views/templates.xml
-
<div class="oe_structure">
-
<div class="container">
-
<h3 t-field="person.name"/>
-
<p>Last modified: <i t-field="person.write_date"/></p>
-
<div t-field="person.biography"/>
-
</div>
-
</div>
这个展示为一个计算机的方式并且不易读,我们让他变为易读的格式:
academy/views/templates.xml
-
<div class="oe_structure">
-
<div class="container">
-
<h3 t-field="person.name"/>
-
<p>Last modified: <i t-field="person.write_date" t-options='{"format": "long"}'/></p>
-
<div t-field="person.biography"/>
-
</div>
-
</div>
或者这样:
academy/views/templates.xml
-
<div class="oe_structure">
-
<div class="container">
-
<h3 t-field="person.name"/>
-
<p>Last modified: <i t-field="person.write_date" t-options='{"widget": "relative"}'/></p>
-
<div t-field="person.biography"/>
-
</div>
-
</div>
管理和erp整合
Odoo管理端简介
Odoo管理端非常容易看到。通过网站支持部分部分。我们可以回到管理端通过导航中的Administrator-Administrator(如果登出了需要登录)
odoo的后台概念结构很简单:
1.导航,一个树结构(导航下有子导航)。导航没有子映射。。。
2.动作,动作有多种类型链接,报告,Odoo执行的代码或者数据显示。数据显示动作被称作window action,并根据视图集合告知Odoo要展示给定的模型。
3.视图有一个类型,一个与其对应的分类(列表,图形,日历),和一种模型被展示在视图里的结构。
在Odoo的管理端编辑
一般来说,一个Odoo模型本质上对用户是不可见的。想看见他必须通过动作使他生效,它本身必须可以触及,一般在导航里。
我们来在模型中创建一个导航:
academy/__manifest__.py
'data': [ 'security/ir.model.access.csv', 'views/templates.xml', 'views/views.xml', ], # only loaded in demonstration mode 'demo': [
academy/views/views.xml
-
<odoo>
-
-
<record id="action_academy_teachers" model="ir.actions.act_window">
-
<field name="name">Academy teachers</field>
-
<field name="res_model">academy.teachers</field>
-
</record>
-
-
<menuitem sequence="0" id="menu_academy" name="Academy"/>
-
<menuitem id="menu_academy_content" parent="menu_academy"
-
name="Academy Content"/>
-
<menuitem id="menu_academy_content_teachers"
-
parent="menu_academy_content"
-
action="action_academy_teachers"/>
接着访问http://localhost:8069/web/在左上角会出现导航Academy,默认被选作第一导航,会打开教师列表。在列表中,可以创建新的教师记录,并通过记录视图转换到表单。
如果没有关于如何呈现一个记录(视图)的定义,Odoo将会自动创建一个基础的。在我看来,他适用于列表视图(只是展示教师的名字),但是在表单视图中HTML的biography字段和name字段一起被展示,并没有给出足够的空间。让我们用视图定义一个客户表单视图,来更好的展示和编辑教师的字段:
academy/views/views.xml
-
<field name="res_model">academy.teachers</field>
-
</record>
-
-
<record id="academy_teacher_form" model="ir.ui.view">
-
<field name="name">Academy teachers: form</field>
-
<field name="model">academy.teachers</field>
-
<field name="arch" type="xml">
-
<form>
-
<sheet>
-
<label for="name"/> <field name="name"/>
-
<label for="biography"/>
-
<field name="biography"/>
-
</sheet>
-
</form>
-
</field>
-
</record>
-
-
<menuitem sequence="0" id="menu_academy" name="Academy"/>
-
<menuitem id="menu_academy_content" parent="menu_academy"
-
name="Academy Content"/>
模型间的关联
我们可以看到一对基础字段直接存进记录。这里有大量的基础字段。第二类字段是关系型的,用于记录间的链接(在模型中或者通过模型)。
在示例中,我们创造了courses模型,每一个课程都需要有一个teacher字段,链接一个单一的教师记录,但是一个教师可以教多门课。
academy/models/models.py
name = fields.Char() biography = fields.Html() class Courses(models.Model): _name = 'academy.courses' name = fields.Char() teacher_id = fields.Many2one('academy.teachers', string="Teacher")
academy/security/ir.model.access.csv
-
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-
access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0
-
access_academy_courses,access_academy_courses,model_academy_courses,,1,0,0,0
让我们同样添加视图,我们就可以看见和编辑课程的教师了:
academy/views/views.xml
-
</field>
-
</record>
-
-
<record id="action_academy_courses" model="ir.actions.act_window">
-
<field name="name">Academy courses</field>
-
<field name="res_model">academy.courses</field>
-
</record>
-
<record id="academy_course_search" model="ir.ui.view">
-
<field name="name">Academy courses: search</field>
-
<field name="model">academy.courses</field>
-
<field name="arch" type="xml">
-
<search>
-
<field name="name"/>
-
<field name="teacher_id"/>
-
</search>
-
</field>
-
</record>
-
<record id="academy_course_list" model="ir.ui.view">
-
<field name="name">Academy courses: list</field>
-
<field name="model">academy.courses</field>
-
<field name="arch" type="xml">
-
<tree string="Courses">
-
<field name="name"/>
-
<field name="teacher_id"/>
-
</tree>
-
</field>
-
</record>
-
<record id="academy_course_form" model="ir.ui.view">
-
<field name="name">Academy courses: form</field>
-
<field name="model">academy.courses</field>
-
<field name="arch" type="xml">
-
<form>
-
<sheet>
-
<label for="name"/>
-
<field name="name"/>
-
<label for="teacher_id"/>
-
<field name="teacher_id"/>
-
</sheet>
-
</form>
-
</field>
-
</record>
-
-
<menuitem sequence="0" id="menu_academy" name="Academy"/>
-
<menuitem id="menu_academy_content" parent="menu_academy"
-
name="Academy Content"/>
-
<menuitem id="menu_academy_content_courses"
-
parent="menu_academy_content"
-
action="action_academy_courses"/>
-
<menuitem id="menu_academy_content_teachers"
-
parent="menu_academy_content"
-
action="action_academy_teachers"/>
他需要在教师的页面也能直接创造新的课程,或者看到所有他要教授的课程,所以在教师模型中添加转换关系。
academy/models/models.py
-
name = fields.Char()
-
biography = fields.Html()
-
-
course_ids = fields.One2many('academy.courses', 'teacher_id', string="Courses")
-
-
class Courses(models.Model):
-
_name = 'academy.courses'
academy/views/views.xml
-
<form>
-
<sheet>
-
<label for="name"/> <field name="name"/>
-
-
<label for="biography"/>
-
<field name="biography"/>
-
-
<field name="course_ids">
-
<tree string="Courses" editable="bottom">
-
<field name="name"/>
-
</tree>
-
</field>
-
</sheet>
-
</form>
-
</field>
讨论和通知
Odoo提供技术模型,虽然不能直接满足业务需要,但是并不需要亲手创建他们就可以扩展业务对象的能力。
其中有一个叫做Chatter的系统,拥有Odoo的email和信息系统的部分功能,能够将通知和讨论功能添加到任何模型中。模型只要继承 mail.thread,并在表单视图中添加message_ids字段来显示讨论线程。讨论线程是预记录。
对于我们的academy,允许通过讨论的方针来调整教师和助手的课程变化或者商讨。
academy/models/models.py
-
class Courses(models.Model):
-
_name = 'academy.courses'
-
_inherit = 'mail.thread'
-
-
name = fields.Char()
-
teacher_id = fields.Many2one('academy.teachers', string="Teacher")
academy/views/views.xml
-
<label for="teacher_id"/>
-
<field name="teacher_id"/>
-
</sheet>
-
<div class="oe_chatter">
-
<field name="message_follower_ids" widget="mail_followers"/>
-
<field name="message_ids" widget="mail_thread"/>
-
</div>
-
</form>
-
</field>
-
</record>
在每一个课程表格的下方,有一个讨论线程,可能为系统的用户留下信息,跟随或者不跟随的讨论链接到指定的课程。
卖课
Odoo允许提供业务模型,允许更直接的使用或者选择业务需求。比如website_sale模块,安装了一个e-commerce网站,基于Odoo系统上的产品。我们可以容易的 通过把我们的课程制作为产品,实现课程的订阅。
相比于之前传统的继承,这意味着要通过产品模型替换我们的课程模型,并扩展产品的原状(为他添加一切我们需要的东西)。
首先我们需要添加一个依赖:website_sale,所以我们有products(通过sale)和ecommerce接口:
academy/__manifest__.py
-
'version': '0.1',
-
-
# any module necessary for this one to work correctly
-
'depends': ['website_sale'],
-
-
# always loaded
-
'data': [
重启Odoo,升级你的模型,现在你的网站是一个商店了,排列了大量的预填充的产品(通过展示数据)。
第二部是替换课程模型通过product.template,并为课程添加行的产品分类:
academy/__manifest__.py
-
'security/ir.model.access.csv',
-
'views/templates.xml',
-
'views/views.xml',
-
'views/data.xml',
-
],
-
# only loaded in demonstration mode
-
'demo': [
academy/views/data.xml
-
<odoo>
-
<record model="product.public.category" id="category_courses">
-
<field name="name">Courses</field>
-
<field name="parent_id" ref="website_sale.categ_others"/>
-
</record>
-
</odoo>
academy/views/demo.xml
-
<field name="name">Lester Vaughn</field>
-
</record>
-
-
<record id="course0" model="product.template">
-
<field name="name">Course 0</field>
-
<field name="teacher_id" ref="padilla"/>
-
<field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
-
<field name="website_published">True</field>
-
<field name="list_price" type="float">0</field>
-
<field name="type">service</field>
-
</record>
-
<record id="course1" model="product.template">
-
<field name="name">Course 1</field>
-
<field name="teacher_id" ref="padilla"/>
-
<field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
-
<field name="website_published">True</field>
-
<field name="list_price" type="float">0</field>
-
<field name="type">service</field>
-
</record>
-
<record id="course2" model="product.template">
-
<field name="name">Course 2</field>
-
<field name="teacher_id" ref="vaughn"/>
-
<field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
-
<field name="website_published">True</field>
-
<field name="list_price" type="float">0</field>
-
<field name="type">service</field>
-
</record>
-
-
</odoo>
academy/models/models.py
-
name = fields.Char()
-
biography = fields.Html()
-
-
course_ids = fields.One2many('product.template', 'teacher_id', string="Courses")
-
-
class Courses(models.Model):
-
_inherit = 'product.template'
-
-
teacher_id = fields.Many2one('academy.teachers', string="Teacher")
academy/security/ir.model.access.csv
-
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-
access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0
academy/views/views.py
-
</field>
-
</record>
-
-
<menuitem sequence="0" id="menu_academy" name="Academy"/>
-
<menuitem id="menu_academy_content" parent="menu_academy"
-
name="Academy Content"/>
-
<menuitem id="menu_academy_content_teachers"
-
parent="menu_academy_content"
-
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
-
<div class="oe_structure"/>
-
</t>
-
</template>
-
-
<template id="product_item_hide_no_price" inherit_id="website_sale.products_item">
-
<xpath expr="//div[hasclass('product_price')]/b" position="attributes">
-
<attribute name="t-if">product.price > 0</attribute>
-
</xpath>
-
</template>
-
-
<!-- <template id="object"> -->
-
<!-- <h1><t t-esc="object.display_name"/></h1> -->
-
<!-- <dl> -->
我们要做的第二个改变时使产品分类条默认:Customize-Product分类让我们触发一个产品分类树的开关(被用于主显示的过滤)
这部分可以通过扩展模板的customize_show和active字段完成:一个扩展模板(就像我们刚创建的一样)能够被customize_show=True。这个选择将在定制菜单中展示视图,定制菜单有个checkbox框,允许管理员**或者关闭他们(很容易设定他们的网站页面)
我们简单的需要改变产品分类记录并设置他的默认值为active=True:
academy/views/template.xml
-
</xpath>
-
</template>
-
-
<record id="website_sale.products_categories" model="ir.ui.view">
-
<field name="active" eval="True"/>
-
</record>
-
-
<!-- <template id="object"> -->
-
<!-- <h1><t t-esc="object.display_name"/></h1> -->
-
<!-- <dl> -->
有了它,在academy模块安装的时候,产品分类条将字段**。