原文地址:http://www.cnblogs.com/ygj0930/p/7115315.html
一:模型
【Odoo中,一切皆模型,连视图都是模型。Odoo将各种数据,如:权限数据、类数据、视图数据等,按照模型分表存储,然后在查看时,按照索引从各个表格读取信息,组合成我们看到的内容。】
1:创建模型
模型属性:模型类可以使用一些属性来控制它们的一些行为:
_name :创建odoo模型的内部标识符,必含项。
_description :当用户界面显示模型时,一个方便用户的模型记录标题。
_order :当浏览模型记录或者显示在列表视图时,设置默认顺序。
_rec_name:用来指出引用关联字描述记录的字段,例如多对一关系。 默认情况下,它使用name字段,这是模型中常见的字段。但是这个属性允许我们使用任何其他字段来实现这个目的。
_table:用来支持模型的数据库表名。通常,它是左自动计算,是下划线取代点的模型名称,但也可以设置特定的表名。
_inherit :继承。
_inherits :嵌入式继承。
模型深入:
Odoo模型由Python类表示。
Odoo模型被保存在一个中央注册中心,它可以引用实例中可用的所有模型类,并且它可以被一个模型名引用。在我们编写的模型方法代码中,可以通过 self.env['x'] 获取一个代表model x的类的引用。(相当于spring托管对象)
模型名称很重要,因为它们是用于访问注册中心的。模型名称的约定规则:用点分隔的小写字母列表。
模型名称必须是全局唯一的。正因为如此,第一个词应该对应于该模块涉及到的主要应用程序。
瞬态和抽象模型:
绝大多数Odoo模型中,类都是基于models.Model类的。 这种类型的模型具有永久的数据库持久性:为它们创建数据库表,并且它们的记录被存储,直到被显式删除。
Odoo还提供了另外两种模型类型:瞬态模型和抽象模型。
瞬态模型基于models.TransientModel类,用于向导式的用户交互。 它们的数据仍然存储在数据库中,但期望是临时的。 一个清理作业定期从这些表中清除旧数据。
抽象模型基于models.AbstractModel类,并且它不存储数据。 抽象模型作为可重用的功能集,利用Odoo的继承功能,混入到其他模型。
2:模型之间的关系
命名字段时,有以下约定:以_id、_ids为结尾命名的字段,分别对应的是2one和2many的关系。
多对一关系:Many2one关系需要两个参数:关联模块和展示字符。它会在数据库表中创建一个拥有外键的字段去关联数据库表。其他参数:
ondelete 在关联的记录被删除时,将会触发。默认值是null,也就是说,当关联的记录被删除时,它将被置空。其它值为restrict,当记录被关联时,禁止删除,cascade,删除关联记录的同时删除当前记录。
context是一个数据字典,在web客户端视图,通过关联关系访问时,会将上下文传过去。比如,设置默认值。它的详细的介绍,在第六章-视图-设计用户界面中。
domain是一个由多个元组组成的列表的域表达式,用来删选关联字段中有效的记录。
auto_join=True使用这个参数后,将允许ORM在数据查询是使用SQL的join(拼接,级联)功能。
多对多关系:Many2many 最少要提供一个参数,也就是关联的模块,建议再使用string参数,以便更好的标题展示。
多对多关系的存储:在数据库层面,数据库表中是不会添加任何字段。它会自动的创建一个新的中间表,这个表只有两个外键ID字段,并且这两个字段分别关联对应的数据库表。
一对多反向关系:One2many按顺序接收3个参数:关联的模块,关联模块的字段名称,标题文本。最开始的两个参数通常是模块名和相反关系对应的外键字段名。
分层关系:树型存储。
_parent_store = True
# _parent_name = 'parent_id'
parent_id = fields.Many2one('todo.task.tag', 'Parent Tag', ondelete='restrict')
parent_left = fields.Integer('Parent Left', index=True)
parent_right = fields.Integer('Parent Right', index=True)
#添加一个子记录
child_ids = fields.One2many('todo.task.tag', 'parent_id', 'Child Tags')
3:计算字段
要创建计算字段,需要设置它的compute
属性为方法名。这个计算方法通过计算self
的每条记录来设置字段的值。
注意
self
是一个记录的有序集合,它支持标准的Python集合操作,如len(self)
和iter(self)
,加上额外的集合操作recs1 + recs2
。迭代过程逐个提供self
记录,其中每个记录本身是大小为1的集合。你可以通过点记号来访问/分配单个记录上的字段record.name
。
计算字段就像常规字段一样声明,但是有额外的compute参数,参数值是一个函数名,在函数中计算值并返回。
字段= fields.XX(compute='函数名')
@api.depends('参数')
def 函数(self):
操作
当计算依赖于其他字段时,需要@api.depends装饰器。
计算字段的值通常取决于所在记录行的其它字段的值。ORM层期望开发人员使用depends()
装饰器来指定计算方法的依赖性。当某些依赖关系被修改后,ORM层通过给定的依赖关系来触发字段的重新计算。
一种用法:统计一对多字段的长度,得到关联人数:
attendees_count = fields.Integer(string="Attendees count", compute='_get_attendees_count', store=True)
@api.depends('attendee_ids')
def _get_attendees_count(self):
for r in self:
r.attendees_count = len(r.attendee_ids) //根据关联字段的长度,得到出席人数
onchange:【onchange相当于前端的js函数!】
"onchange"机制为客户端界面提供了一种方法:当用户在字段中填写了值,不需要向数据库保存任何内容,就可以更新表单。
例如,假设模型有三个字段amount
,unit_price
和price
,当数量和单价改变时,自动重新计算价格,并在表单界面更新。要实现这个需求,需要定义一个方法,并使用onchange()
装饰器,onchange()
的参数指定了在那个字段改变时,触发方法。其中self
代表表单视图中的记录,你所做的任何更改,self
都将立刻反应在表单上。
onchange也可以用于检测字段变化值是否合法。
搜索与写入:
计算字段可以通过计算得到字段值,但此时只能被读取显示,还不能被搜索或者写入。为此,我们需要实现函数,并通过字段的search参数、inverse参数来实现该字段的搜索与写入定义。
字段= fields.XX( string='展示名', compute='计算函数', search='搜索函数', inverse='写入函数') def 搜索函数(self, 参数): return [('搜索条件', operator, value)]
def 写入函数(self): self.字段 = self.写入值
存储计算字段:通过设置“store= true”的定义,计算字段的值也可以存储在数据库中。
4:关联字段
字段 = fields.XX(
related='关联模型.关联字段',
string='展示名')
5:模型约束
Python约束检查函数应该使用@api.constraints(被约束字段) 修饰,说明被检查的字段的列表。当其中任何一个被修改,并且在条件失败时将会抛出一个异常,验证就会被触发。
@api.constrains('字段名')
def 验证函数(self):
if 条件:
raise ValidationError('验证错误信息!')
6:self.env
self.env 对象给出了访问请求参数和其他有用的信息:
self.env.cr 或者 self._cr是数据库游标对象,通常用于查询数据库
self.env.uid或者self._uid是当前用户的数据库ID
self.env.user是当前用户记录
self.env.ref(xml_id)返回XML ID对应的记录
self.env[model_name]返回给定模型的实例
二:视图
用户界面的每个组件都以记录的形式存储在数据库中,模块从XML文件加载相应的数据时会向数据库添加UI元素,然后odoo从数据库读取UI元素进行显示。
菜单项:
<menuitem>快捷元素,提供了一种缩减方式来定义要加载的记录,我们可以使用它来代替<record model =“ir.ui.menu”>元素。
顶级菜单项:只有id和name属性。
子菜单项:通过parent =“上层菜单id”属性置于上层菜单下。
菜单动作:通过action =“act_window”属性,把点击菜单的动作指定为act_window中打开某个视图(如tree/form)
菜单分组:使用groups属性使其仅对某些安全组可见。
窗口动作:
给出GUI客户端指令,通常供视图中的菜单项或按钮调用。
它告诉GUI应该使用什么模型,以及提供哪些视图。 这些操作可以使用domain过滤器强制只有一部分记录可见。 他们还可以通过context属性设置默认值和过滤器。
窗口动作存储在ir.actions.act_window模型中,可以使用<act_window>快捷标签在XML文件中定义。
主要属性有:
name:通过此操作打开的视图中显示的标题。 res_model:目标模型的标识符ID view_mode:要打开的视图类型和它们的顺序。 第一个是默认打开的。 target:如果设置为new,将在弹出的对话框窗口中打开视图。 默认值为current,在主内容区域中打开视图。 context:设置关于目标视图的上下文信息,上下文中可以设置默认值或激活过滤器以及其他信息。 domain:域表达式,强制过滤在打开的视图中可浏览的记录。 limit:列表视图中每个页面的记录数。
src_model:应该在什么模型上此动作可用。
multi:当设置为True时,使它在列表视图中可用,以便它可以应用于多条选中的记录。 默认值为False。
上下文与域:
context属性值:上下文是一个包含session数据的字典,它可以被客户端的用户接口和服务器端的ORM与业务逻辑使用。
在客户端,它可以将信息从一个视图传输到另一个视图。在服务器端,一些记录的字段值可以通过上下文被本地设置提供。
domain表达式:域被用来筛选数据记录。它们使用特殊的语法,以便于Odoo ORM 将它们解析后生成对应的SQL WHERE数据库筛选语句。
域表达式是一个条件列表,每个条件是一个形如('field_name', 'operator', value')的元组。
filed_name 是需要筛选的字段,它可以使用点(.)来访问关系模块的字段。
value 是一个Python表达式的值。它可以使用字符值,比如:字符串,数字,布尔值,或则列表、某个字段、用户在context中自定义的有效的值。
operator 可以为:
常用的操作符:<,>,<=,>=,=,!=。
'=like'通配符,使用下划线(_)时,匹配一个任意字符,使用百分号(%)时,匹配多个字符。
'like'匹配一个’%value%’的字符串。’ilike’与此类似但不区分大小写。‘not like’和‘not ilike’也可以使用
'child of'在层级关系中,筛选子集
'in'和’not in’筛选是否在一个列表里面,所以,给的值应该是个list。当在’to-many’的关系字段中,‘in’的作用和contains的作用一样
domain表达式是一个包含多项内容的list,因此,可以包含多个条件表达式元组。 默认情况下(隐含),这些条件之间是用AND逻辑符连接的,也就是说,它只返回满足所有条件的记录集。
也可以用显式的逻辑连接符:and连接符(&,默认使用),或连接符(|)。这些连接符后面跟着两项内容,可以画成递归树的形式理解。
感叹号(!),是非操作符(NOT),作用于紧挨它的后一个项。因此,它应该出现在否定项的前面。比如,['!', ('is_done','=',True)]
['|', ('message_follower_ids', 'in', [user.partner_id.id]),
'|', ('user_id', '=', user.id), ('user_id', '=', False)]
画成递归树:
窗体视图:form视图
Header头部:header区域一般用于展示文档流转的阶段和生命周期,以及动作按钮。
文档生命周期通过状态栏小控件呈现当前所处的状态.这些通常是状态选择字段或者多对一的阶段字段。
状态是一个选择列表,呈现的是过程中有几个相当稳定的步骤阶段,例如:新建、处理中、完成。
操作按钮一般为表单按钮,最重要的阶段可以使用class=“oe_highlight”突出显示。
Sheet区域:
标题:在group之外,我们可以使用html基本元素来制定标题,如:div,span,H1,和H2等。
分组:<newline>将强制生成一个新行。附加部分标题可以使用<separator>元素添加到组内。使用col和colspan属性,我们可以更好的控制组元素布局。col属性可以指定组中包含的列数,默认值是2,它也可以改为任何数字,双数的效果更好,因为每一个字段加起来都要两列。组内元素,包括<field>元素,可以使用colspan属性设置一个特定的列数,默认都是一列。
分页笔记本:笔记本元素可以包含多个标签的部分,称为页面。可以实现按页切换输入、显示。
<notebook>
<page string="显示文字" name="页名">
内容...
</page>
<page>
...
</page>
</notebook>
语义组件:
视图标签属性:
name:标识字段数据库名称
string:标签文本,如果我们想要覆盖模型定义提供的标签文本,可以使用它。
help:提示文本,当您将指针悬停在字段上时,将显示一个提示文本,并允许覆盖模型定义提供的帮助文本。
placeholder:是一个建议文本,显示在该字段内。
widget:允许我们覆盖用于该字段的缺省小部件。
options:是一个JSON数据结构,为小部件提供了额外的选项,并且取决于每个小部件支持什么。
class:是用于字段HTML呈现的CSS类。
nolabel="True":防止自动字段标签被呈现。仅对<group>元素中的字段有意义,并且经常和<label for="..."> 元素一起使用.
invisible="True":使字段不可见,但是数据是从服务器获取的,并且在表单上可用。
readonly="True": 使表单上的字段不可编辑。
required="True" 在表单上字段为必需字段。
某些字段类型的特殊属性:
password="True":用于文本字段。它显示为一个密码字段,屏蔽输入的字符。
filename: 用于二进制字段,它是用于存储上传文件名称的模型字段名称。
mode:用于一对多字段。它指定用于显示记录的视图类型。默认情况下,它是树,但也可以是表单、看板或图形。
小部件(widget属性值):
对于文本字段,我们有以下小部件:
email:是用来将电子邮件文本转换为一个可操作的“邮件”地址。
url :用于将文本格式化为可单击的url。
html:用于渲染文本作为html内容;在编辑模式下,以WYSIWYG编辑器,允许内容的格式,而不需要使用HTML语法。
对于数值字段,我们有以下小部件:
handle:是专门为列表视图中的序列字段设计的,并显示一个句柄,允许您将行拖到一个定制的顺序。
float_time:拥有小时和分钟的时间浮点字段格式.
monetary:作为货币金额显示浮动字段。它需要一个currency_id伙伴字段,另一个字段名称可以设置选项=“{ 'currency_field ':' currency_id“}”。
progressbar 用一个浮点数表示为一个进度百分比,并且可以用于表示完成率字段.
对于关系和选择字段,我们有这些附加的小部件:
many2many_tags : 显示按钮标签列表值.
selection:用于多对一字段的选择字段部件。
radio 使用单选按钮显示选择字段选项.
kanban_state_selection展示了看板状态选择列表的信号灯。一般状态为灰色,已经完成为绿色,其他状态为红色.
priority 一个可点击的星星列表的选择字段。可选项一般为数字.
按钮(button元素)属性:
icon 可用的按钮图标在 addons/web/static/src/img/下
string 按钮的显示文字
type 是动作执行类型。可能值是:workflow, object,action 默认是 workflow:
workflow 用于触发工作流引擎信号;
object 用于调用Python方法;
action 用于运行窗口动作。
name 触发的方法标识:工作流信号名、模型方法名称或运行窗口操作的数据库ID。
args 传递方法的参数
context 将值添加到上下文
confirm 针对对话框的确认
special="cancel" 用于向导,用来取消和关闭向导表单。
class 加载的类名(常用 oe_highlight)
动态视图:
视图元素也支持一些动态属性,允许动态视图根据字段值来改变他们的外观或行为。
其他视图:
日历视图:
<field name="arch" type="xml">
<calendar date_start="字段" color="颜色"
display="[name], Stage [stage_id]" >
日历视图属性:
date_start开始日期的字段,必需字段。
date_end结束日期的字段,可选字段。
date_delay持续天数的字段,可以使用代替date_end。
all_day提供一个布尔字段是用来发送全天事件信号。
color 日历条目颜色分组的字段 。这个字段中的每个不同的值将被分配一个颜色,并且该字段所有同值的条目将具有相同的颜色。
display 是每个日程表条目的显示文本. 它使用方括号加字段名称表示用户记录值,例如[name]。
mode 是日历的默认显示模式,无论是一天、一周还是一个月。
图形视图:
<graph type="bar">
...
</graph>
图形视图元素可以有一个类型属性,可以设置为条形(默认)、饼状或线。在条形的情况下,可以使用stacked="True"呈现堆叠在一起的条形图。
枢轴视图:
<pivot>
....
</pivot>