环境
odoo-14.0.post20221212.tar
ORM API学习总结/学习教程
模型(Model)
Model字段被定义为model自身的属性
from odoo import models, fields class AModel(models.Model): _name = 'a.model.name' field1 = fields.Char()
警告
字段的名称和方法的名称不能相同,最后定义的方法、函数名称会覆盖前面定义的相同名称。
默认的,字段的标签(Lable,即用户可见字段名称)为对应字段名称开头字母改成大写后的值,可通过 string
字段属性改成修改字段Label
field2 = fields.Integer(string="Field Label")
可通过default
,定义默认值:
name = fields.Char(default="a value")
默认值也可以通过函数获取:
def _default_name(self): return 'Title' name = fields.Char(default=lambda self: self._default_name())
API
BaseModel
class odoo.models.BaseModel
[源代码]
Odoo模型的基类。Odoo mode可通过继承一下类来创建Model:
Model
用于常规数据库持久化模型TransientModel
用于临时数据,存储在数据库中,但每隔一段时间就会自动清空AbstractModel
用于多继承模块共享的抽象父类,不会在数据库中创建模型表
系统为每个数据库自动实例化每个模型一次。这些实例表示每个数据库上的可用模型,取决于该数据库上安装的模块。每个实例的实际类都是从创建和继承相应模型的Python类构建的。
每个模型实例都是一个“记录集(recordset)”,即模型记录的有序集合。记录集由 browse()
, search()
或字段访问等方法返回。记录没有显式的表示:单条记录表示为一条记录的记录集。
要创建不需要实例化的类,可以将 _register
属性设置为False
_auto= False
是否应该创建数据库表。如果设置为False
, 应该重写init()
来创建数据库表。默认设。针对Model
和TransientModel
自动设置为False
,针对AbstractModel
自动设置为False
。可通过继承AbstractModel
来创建不需要任何数据表的模型_log_access
ORM是否自动生成和更新 Access Log fields。默认_auto
的值。_table= None
模型对应的数据库表的名称。如果_auto
设置为True
的话。_sequence= None
用于ID字段的SQL序列_sql_constraints= []
sql约束,格式:[(name, sql_def, message)]
_register= True
registry visibility_abstract= True
是否为抽象模型_transient= False
是否为transient模型_name= None
模型名称(以 点分式命名的模块名称,比如estate.users
)_description= None
模块描述,非整数名称_inherit= None
继承的Python模型:需要继承模型的名称(_name
属性值)或者名称列表(list
类型)_inherits= {}
(不太理解)
dictionary {‘parent_model’: ‘m2o_field’} mapping the _name of the parent business objects to the names of the corresponding foreign key fields to use:
_inherits = { 'a.model': 'a_field_id', 'b.model': 'b_field_id' }
- implements composition-based inheritance: the new model exposes all the fields of the inherited models but stores none of them: the values themselves remain stored on the linked record.
警告
if multiple fields with the same name are defined in the_inherits
-ed models, the inherited field will correspond to the last one (in the inherits list order). _rec_name= None
用于标记记录的字段,默认值:name
_order= 'id'
用于搜索结果的默认排序字段_check_company_auto= False
执行write
和create
, 对拥有check_company=True
属性的关联字段调用_check_company
以确保公司一致性_parent_name= 'parent_id'
用作父字段的many2one字段_parent_store= False
设置为True
以计算parent_path
字段。与parent_path
字段一起,设置记录树结构的索引存储,以便使用child_of
和parent_of
域运算符对当前模型的记录进行更快的分层查询_date_name= 'date'
用于默认日历视图的字段_fold_name= 'fold'
用于确定看板视图中折叠组的字段
AbstractModel
odoo.models.AbstractModel
[源代码]
odoo.models.BaseModel
的别名
Model
class odoo.models.Model
[源代码]
常规数据库持久化Odoo模型的主要父类。
通过继承此类来创建Odoo模型的:
class user(Model): ...
系统将为安装了该类模块的每个数据库实例化一次类
_auto= True
是否应该创建数据库表。如果设置为False
, 应该重写init()
来创建数据库表。默认设。针对Model
和TransientModel
自动设置为False
,针对AbstractModel
自动设置为False
。可通过继承AbstractModel
来创建不需要任何数据表的模型_abstract= False
是否为抽象模型_transient= False
是否为transient模型
TransientModel
class odoo.models.TransientModel
[源代码]
用于临时记录的父类模型,旨在暂时保持,并定期进行清理
TransientModel
具有简化的访问权限管理,所有用户都可以创建新记录,并且只能访问他们创建的记录。超级用户可以无限制地访问所有TransientModel
记录。
_auto= True
是否应该创建数据库表。如果设置为False
, 应该重写init()
来创建数据库表。默认设。针对Model
和TransientModel
自动设置为False
,针对AbstractModel
自动设置为False
。可通过继承AbstractModel
来创建不需要任何数据表的模型_abstract= False
是否为抽象模型_transient= False
是否为transient模型
字段(Fields)
class odoo.fields.Field[源代码]
字段拥有以下属性
- string (str) – 用户看到的字段的标签;如果未设置,ORM将采用类中的字段名开头字母改成大写后的
- help (str) – 用户看到的字段的提示条(设置该属性后,当鼠标悬停在字段标签上方时,会自动浮现提示条,显示该属性的文字内容)。
- invisible – 字段是否可见。默认为
False
,即可见 - readonly (bool) – 字段在用户界面是否只读,默认值
False
,仅对UI起作用 - required (bool) – 字段在用户界面是否必填,默认
False
。这通过在数据库层面为列添加NOT NULL
约束来实现 - index (bool) – 是否为字段添加索引。注意:对不存储、虚拟字段不起作用。默认值:
False
- default (值或者可调用对象) – 设置字段的默认值。可以是静态值,或者以结果集为入参,返回某个值的函数。使用
default=None
舍弃该字段的默认值。 - states (dict) –将
state
值映射到UI属性-值对列表的字典映射,简单说就是允许用户界面依据state
字段的值来动态设置对应字段的UI属性,因此,它要求存在一个state
字段并在视图中使用(即使是隐藏的),state
属性的名称是在odoo硬编码且不允许修改的,可用属性有:readonly
,required
,invisible
。例如states={'done':[('readonly',True)]}
,表示当state
值为done
时,将用户界面states
所在字段在设置为只读(仅针对UI层面)
用法举例:
state = fields.Selection([ ('draft', 'To Submit'), ('cancel', 'Cancelled'), ('confirm', 'To Approve'), ('refuse', 'Refused'), ('validate1', 'Second Approval'), ('validate', 'Approved') ], string='Status', readonly=True, copy=False, default='confirm') date_from = fields.Datetime( 'Start Date', readonly=True, index=True, copy=False, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
- groups (str) – 值为逗号分隔的组XML ID列表,如
groups='base.group_user,base.group_system'
,可限制字段只能被给定组用户访问。 - company_dependent (bool) –
字段值是否依赖于当前公司,如果设置为True
,则表示依赖当前公司,即字段值和公司绑定。这个属性的作用就是让同一字段,可以根据不同公司,存储不同的值,假设一个用户属于多个公司,他在不同公司的职务也不一样,此时就可以设置该属性为True
。
该值未存储在当前模型表中。它注册为ir.property
,也就是说它的值存储在ir_property
表中,通过查询该表来获取该字段的值。 - copy (bool) – 当记录重复时,该字段值是否被拷贝(在使用 ORM
copy()
方法复制并生成新记录时,不复制该字段的值)。 (针对普通字段,默认值为:True
,针对one2many
和计算字段,包括属性字段(property fields
,个人理解注册ir.property
的字段)和关系字段,默认值为False
- store (bool) – 该字段是否存储到数据库,针对计算字段,默认值为
False
,其它字段默认为True
- group_operator(str) –在当前字段上分组时,供
read_group()
使用的聚合函数支持的聚合函数:
array_agg
: 值,包括空值,连接成一个数组count
: 记录数count_distinct
: 不重复记录数bool_and
: 如果所有值都为真,则为真,否则为假bool_or
: 如果至少有一个值为真,则为真,否则为假max
: 所有值的最大值min
: 所有值的最小值avg
:所有值的平均值(算术平均值)sum
: 所有值的总和
- group_expand (str) –
用于在当前字段上分组时用于扩展read_group
结果的函数
@api.model def _read_group_selection_field(self, values, domain, order): return ['choice1', 'choice2', ...] # available selection choices. @api.model def _read_group_many2one_field(self, records, domain, order): return records + self.search([custom_domain])
基础字段
class odoo.fields.Boolean[源代码]
bool
的封装
class odoo.fields.Char[源代码]
基本字符串字段,长度有限,通常在客户端显示为单行字符串
参数:
- size(int) – 为该字段可存储最大值
- trim(bool) – 说明该值是否被修剪(默认情况下,
True
)。请注意,修剪操作仅由 Web 客户端应用。 - translate(bool 或者可调用对象)
– 启用字段值的翻译;用于
translate=True整体翻译字段值;
translate也可以是可调用的,从而使得
translate(callback,value)通过使用
callback(term)来检索术语的翻译来翻译
value`
class odoo.fields.Float[源代码]
float
的封装
精度数字由可选的digitals
属性给出。
参数
- digits (
tuple
(int
,int
), 或者str
) – 一个元组(total, decimal)
或者引用DecimalPrecision
记录的字符串
digits=(8,2) 表示总的8位,小数点占2位
Float类为此提供了一些静态方法:
round()
以给定精度对浮点值进行舍入。is_zero()
检查浮点值在给定精度下是否等于零。compare()
按给定精度比较两个浮点值。
例子:
fields.Float.round(self.product_uom_qty, precision_rounding=self.product_uom_id.rounding)
fields.Float.is_zero(self.product_uom_qty, precision_rounding=self.product_uom_id.rounding)
field.Float.compare(self.product_uom_qty, self.qty_done, precision_rounding=self.product_uom_id.rounding)
比较助手出于历史目的使用__cmp_
语义,因此使用此助手的正确惯用方式如下:
如果result==0,则第一个和第二个浮点数相等,如果result<0,第一个浮点数小于第二个,如果result>0,第一个浮动点数大于第二个浮动点数
class odoo.fields.Integer[源代码]
int
的封装
高级字段
class odoo.fields.Binary[源代码]
封装二进制内容(比如一个文件)。
参数:
- attachment(bool)
– 字段是否存储为
ir_attachment还是该model表的一列(默认为:
True`,即存储为前者。
class odoo.fields.Html[源代码]
html代码内容的封装
参数:略
class odoo.fields.Image[源代码]
图片的封装,扩展Binary
如果图像大小大于像素的max_width/max_height
限制,则通过保持纵横比将图像大小调整到该限制。
参数:
- max_width(int ) – 图像的最大宽度(默认值:
0
,无限制) - max_height ( int) – 图像的最大高度(默认值:
0
,无限制) - verify_resolution ( bool) – 是否应验证图像分辨率以确保它不会超过最大图像分辨率(默认值:
True
。最大图像分辨率请参阅odoo.tools.image.ImageProcess
(默认值:50e6
)。
参数
如果没有指定 max_width
/max_height
或者设置为0,且verify_resolution
为False
,则不会验证字段内容,此时应该使用Binary
字段。
class odoo.fields.Monetary[源代码]
封装以给定res_currency
表示的浮点值。
小数精度和货币符号取自currency_field
属性。
参数:
- currency_field (str) –拥有表示该货币字段的
res_currency
的Many2one
字段名称(默认:'currency_id'
)
class odoo.fields.Selection[源代码]
封装不同值之间的互斥选择。
说明:Selection
字段的可选值,存储在public.ir_model_fields_selection
表中,通过field_id
字段通过public.ir_model_fields
表进行
-- 查询Selection字段ID SELECT id FROM public.ir_model_fields where model = 'stock.quality' and name='state' -- 查询Selection字段可选值 select * from public.ir_model_fields_selection where field_id = 13028; -- 13028为Selection字段ID
参数:
- selection (list(tuple(str, str)) 或者可调用对象 或者 str)) – 指定字段的可选值。其值为包含2元组的列表,或者返回前者模型方法,或者方法名称
- selection_add (list(tuple(str, str)) –
在重写字段的情况下,提供selection
的扩展。它是一个包含二元组(value, label)
或者单元组(value,)
的列表,其中,单元组中的value
必须作为value
出现在selection
列表中的元组中。新值插入顺序和原有selection
中元组顺序保持一致:
selection = [('a', 'A'), ('b', 'B')] selection_add = [('c', 'C'), ('b',)] > result = [('a', 'A'), ('c', 'C'), ('b', 'B')]
- ondelete–为带有
selection_add
的任何重写字段提供回退机制。这是一个将selection_add
中的每个选项映射到回退操作的dict。此回退操作将应用于其selection_add
选项映射到该操作的所有记录。这些操作可以是以下任一操作:
set null
默认情况下,具有此选项的所有记录的选择值都将设置为False。cascade
–具有此选项的所有记录将与选项本身一起删除。set default
-具有此选项的所有记录都将设置为字段定义的默认值<callable>
-一个可调用对象,其第一个也是唯一的参数将是包含指定的Selection选项的记录集,用于自定义处理
selection
属性选择是强制性的,除非是related
或扩展的字段
class odoo.fields.Text[源代码]
类似Char
,用于更长的内容,没有大小,通常展示为多行文本框。
参数:
translate (bool 或者可调用对象) – 同 Char
Date(time) 字段
当将一个值赋值给 Date
/Datetime
字段时,以下选择是合法的:
date
或datetime
对象.- 正确格式的字符:
Date
字段采用YYYY-MM-DD
Datetime
字段采用YYYY-MM-DD HH:MM:SS
False
或者None
.
Date
和Datetime
字段类拥有以下辅助函数,用于尝试转换为兼容类型:
to_date()
转换为datetime.date
to_datetime()
转换为datetime.datetime
.
示例
解析来自外部的日期/日期时间:
fields.Date.to_date(self._context.get('date_from'))
Date
/Datetime
比较最佳实践:
Date
字段只能和date对象比较Datetime
字段只能和datetime对象比较
Datetime
字段在数据库中存储为不带时区的时间戳,并以UTC时区存储。因为这样可使Odoo数据库独立于托管服务器系统的时区。时区转换完全由客户端管理。
Common operations with dates and datetimes such as addition, subtraction or fetching the start/end of a period are exposed through both Date
and Datetime
. These helpers are also available by importing odoo.tools.date_utils
.
class odoo.fields.Date源代码
Python date
对象的封装
static add(value, *args, **kwargs)
返回value
和relativedelta
之和
- 参数
value – 初始date
或datetime
args – 传递给relativedelta
的位置参数
kwargs – 传递给relativedelta
的关键词参数 - 返回
date/datetime结果对象
- 示例:
from odoo.fields import Date print(Date.add(datetime.now(), years=1)) # 输出形如:2024-01-03 # 常见参数: # years, months, days, leapdays, weeks, hours, minutes, seconds, microseconds
static subtract(value, *args, **kwargs)
[源代码]返回value
和relativedelta
之差
- 参数
value – 初始date
或者datetime
args – 传递给relativedelta
位置参数
kwargs – 传递给relativedelta
的关键词参数 - 返回
date/datetime
结果对象
static context_today(record, timestamp=None)
[源代码]按客户端时区以适合date
字段的格式返回当前日期
注解
该方法可能用于计算默认值
- 参数
record – 从中获取时区的记录集
timestamp (datetime
) – 替代当前日期时间(datetime)的可选的datetime
对象 - 返回类型
date
static end_of(value, granularity)
[源代码]从日期或日期时间获取时间段的结束
- 参数
value – 初始date
或datetime
granularity – 字符串表示的时间段类型, 可以是year
,quarter
,month
,week
,day
或者hour
。 - 返回
与指定时段的起始对应的date/datetime
对象
- 示例:
print(datetime.now()) # 2023-01-03 10:12:32.332208 print(Date.end_of(datetime.now(), 'year')) # 输出形如:2023-12-31 23:59:59.999999 print(Date.end_of(datetime.now(), 'month')) # 输出形如:2023-01-31 23:59:59.999999
static start_of(value, granularity)
[源代码]从日期或日期时间获取时间段的开始
- 参数
value – 初始date
或datetime
granularity – 字符串表示的时间段类型, 可以是year
,quarter
,month
,week
,day
或者hour
。 - 返回
与指定时段的起始对应的date/datetime
对象
- 示例:
print(datetime.now()) # 2023-01-03 10:18:57.071276 print(Date.start_of(datetime.now(), 'year')) # 输出形如:2023-01-01 00:00:00 print(Date.start_of(datetime.now(), 'month')) # 输出形如:2023-01-01 00:00:00 print(Date.start_of(datetime.now(), 'hour')) # 输出形如:2023-01-03 10:00:00
static to_date(value)
[源代码]尝试转换value
为date
对象
警告
如果value为
datetime
对象,它将被转换为date
对象,且所有日期时间特定信息(HMS, TZ, …)都会丢失。
- 参数
value (str 或 date 或 datetime) –需要转换的值 - 返回
代表value
的对象 - 返回类型
date
类型或者None
static to_string(value)
[源代码]将date
或者datetime
对象转为字符串
- 参数
value – 需要转换的日期或者日期时间对象 - 返回
以服务器日期格式返回代表value
的字符串。如果value
为datetime
类型,自动舍弃小时,分,秒,时区信息。 - 返回类型:str
- 示例:
print(Date.to_string(datetime.now())) # 输出形如:2023-01-03
static today(*args)
[源代码]
返回当前日期
示例:
print(Date.today()) # 格式形如:2023-01-03
class odoo.fields.Datetime[源代码]
Python datetime
对象的封装
static context_timestamp(record, timestamp)
[源代码]返回转换为客户端时区的给定时间戳。
注解
此方法不是用作默认初始值设定项,因为
datetime
字段在客户端显示时会自动转换。对于默认值,应使用now()
- 参数
record – 从中获取时区的记录集。
timestamp (datetime) – 待转换为客户端时区的naivedatetime
值 (UTC
表示的) - 返回
按上下文时区转换为时区敏感的datetime
- 返回类型
datetime
static add(value, *args, **kwargs)
[源代码]
参考Date.add
static subtract(value, *args, **kwargs)
[源代码]
参考Date.subtract
static end_of(value, granularity)
[源代码]
参考Date.end_of
static start_of(value, granularity)
[源代码]
参考Date.start_of
static to_string(value)
[源代码]
参考Date.to_string
static today(args)
[源代码]
返回当天,午夜 (00:00:00)
示例:
from odoo.fields import Datetime print(Datetime.today()) # 输出形如:2023-01-03 00:00:00 print(Datetime.now()) # 输出当前时间 2023-01-03 12:33:00
static to_datetime(value)
[源代码]将ORMvalue
转为datetime
值
- 参数
value (str 或者 date 或者 datetime) – 需要转换的值 - 返回
代表value
的对象 - 返回类型
datetime
或者None
关系字段(Relational Fields)
class odoo.fields.Many2one
[源代码]
Many2one
字段的值是大小为0(无记录)或1(单个记录)的记录集。
参数:
- comodel_name (str) – 目标模型的名称,
comodel_name
是必选参数,除非是相关或扩展字段(不太理解,原文:name of the target modelMandatory
except for related or extended fields) - domain – 用于设置客户端侧候选值的可选 domain (domain 或者字符串)
- context (dict) – 处理该字段时供客户端使用的上下文
- ondelete (str) – 当引用的记录被删除时,怎么处理:可选值有:
'set null'
,'restrict'
,'cascade'
- auto_join (bool) – 是否在搜索该字段时生成
JOIN
(默认:False
) - delegate (bool) – 将其设置为
True
以标记可通过当前模型访问目标模型的字段(对应_inherits
) - check_company (bool) – 标记需要在
_check_company()
中校验的字段。取决于字段属性,添加一个默认的公司domain
class odoo.fields.One2many
[源代码]
One2many
字段的值为 comodel_name
中所有满足条件的记录的结果集,而目标模型中的 inverse_name
则等价于当前记录。
参数:
- comodel_name (str) – 目标模型的名称
- inverse_name (str) – 目标模型中反向
Many2one
字段名称,根据该字段反向查询记录 - domain – 用于设置客户端候选值的条件 (domain 或者字符串),可选
- context (dict) – 处理该字段时供客户端使用的上下文
- auto_join (bool) – 是否在搜索该字段时生成
JOIN
(默认:False
) - limit (int) – 读取时用的可选限制
comodel_name
和inverse_name
参数是必选参数,除非是相关或者扩展字段
class odoo.fields.Many2many
[源代码]
Many2many
字段的值为一个结果集。
参数:
- comodel_name – 目标模型的名称,必选参数,除非是关联或者扩展字段
- relation (str) – 数据库中存储关系的表名,可选参数。
- column1 (str) –
relation
表中引用"这些"记录的列名,可选参数 - column2 (str) –
relation
表中引用"那些"记录的列名,可选参数
relation
, column1
和column2
参数可选。 如果未给定,自动根据模型名称生成,提供的不同的model_name
和comodel_name
。
注意,ORM不支持在给定模型,使用同样的comodel
,创建多个省略了relation
参数的字段,因为这些字段将使用相同的表。ORM阻止两个Many2many
字段使用相同的relation
参数,除非:
- 两个字段都使用相同的模型,
comodel
并显示指定relation
参数,否则 - 至少有一个字段属于携带
_auto = False
的模型
参数:
- domain – 用于设置客户端候选值的条件 (domain 或者字符串),可选
- context (dict) – 处理该字段时供客户端使用的上下文
- check_company (bool) – 标记需要在
_check_company()
中校验的字段。取决于字段属性,添加一个默认的公司条件 - limit (int) – 读取时用的可选限制
注意:odoo不会在当前模型对应表中为One2many
,Many2many
类型的属性建立对应的表字段,但会为Many2one
类型的属性建立对应表字段,针对Many2many
类型的属性,odoo会建立一张辅助表,表名默认格式为model1_table_name_model2_table_name_rel
,该表拥有两列,一列为当前模型表主键ID(model1_table_name_id
),一列为关系字段关联模型表的主键ID(model2_table_name_id
),这样通过两表记录ID就可以查询所需记录了
伪关系字段
class odoo.fields.Reference
[源代码]
伪关系字段(数据库中没有FK)。该字段值存储为数据库中遵循模式"res_model,res_id"
的字符串。class odoo.fields.Many2oneReference
[源代码]
该字段的值存储为数据库中的一个整数。与odoo.fields.Reference
字段相反,必须在Char
类型字段中指定模型,其中,该字段的名称必须在当前Many2oneReference
字段中的model_field
属性中指定
参数:model_field (str) – 存储模型的字段名称。
计算字段
可以使用 compute
参数计算字段(而不是直接从数据库中读取)它必须将计算值分配给字段。如果它使用其他字段的值,则应使用depends()
指定这些字段
from odoo import api total = fields.Float(compute='_compute_total') @api.depends('value', 'tax') def _compute_total(self): for record in self: record.total = record.value + record.value * record.tax