第 4 章:模型与基础字段¶
在 上一章 的结尾,我们成功创建了一个 Odoo 模块。但此时它仍然是一个空壳,无法存储任何数据。在我们的房地产模块中,我们希望将与房产相关的信息(名称、描述、价格、居住面积……)存储在数据库中。Odoo 框架提供了简化数据库交互的工具。
在继续练习之前,请确保 estate 模块已安装,即它必须在应用列表中显示为“已安装”。
Warning
不要使用可变的全局变量。
一个 Odoo 实例可以在同一个 Python 进程中并行运行多个数据库。不同的模块可能安装在这些数据库中的某一个上,因此我们不能依赖于会根据已安装模块而更新的全局变量。
对象关系映射¶
参考:与此主题相关的文档可在 模型 API 中找到。
Note
目标:在本节结束时,应已创建 estate_property 表:
$ psql -d rd-demo
rd-demo=# SELECT COUNT(*) FROM estate_property;
count
-------
0
(1 row)
Odoo 的一个关键组件是 ORM 层。该层避免了手动编写大部分 SQL,并提供了可扩展性和安全服务2。
业务对象声明为继承 Model 的 Python 类,这会将它们集成到自动持久化系统中。
可以通过在定义中设置属性来配置模型。最重要的属性是 _name,它是必需的,用于定义模型在 Odoo 系统中的名称。以下是一个模型的最小定义:
from odoo import models
class TestModel(models.Model):
_name = "test_model"
这样的定义足以让 ORM 生成一个名为 test_model 的数据库表。按照惯例,所有模型都位于 models 目录中,并且每个模型都在自己的 Python 文件中定义。
看一看 crm_recurring_plan 表是如何定义的,以及相应的 Python 文件是如何导入的:
该模型定义在文件
crm/models/crm_recurring_plan.py中(见 此处)文件
crm_recurring_plan.py导入于crm/models/__init__.py见 此处)文件夹
models导入于crm/__init__.py见 此处)
Exercise
定义房地产物业模型。
根据 CRM 模块中给出的示例,为 estate_property 表创建相应的文件和文件夹。
文件创建好后,为 estate.property 模型添加一个最小定义。
对 Python 文件的任何修改都需要重启 Odoo 服务器。当我们重启服务器时,我们将添加 -d 和 -u 参数:
$ ./odoo-bin --addons-path=addons,../enterprise/,../tutorials/ -d rd-demo -u estate
-u estate 表示我们想要升级 estate 模块,即 ORM 将应用数据库架构更改。在本例中,它会创建一个新表。-d rd-demo 表示应在 rd-demo 数据库上执行升级。-u 应始终与 -d 结合使用。
启动期间,您应该会看到以下警告:
...
WARNING rd-demo odoo.models: The model estate.property has no _description
...
WARNING rd-demo odoo.modules.loading: The model estate.property has no access rules, consider adding one...
...
如果是这样,那就没问题了!为确保无误,请按照 目标 中的演示用 psql 再次检查。
Exercise
添加描述。
为您的模型添加 _description,以消除其中一条警告。
模型字段¶
参考:与此主题相关的文档可在 字段 API 中找到。
字段用于定义模型可以存储什么以及存储在哪里。字段定义为模型类中的属性:
from odoo import fields, models
class TestModel(models.Model):
_name = "test_model"
_description = "Test Model"
name = fields.Char()
name 字段是一个 Char,它将表示为 Python unicode str 和 SQL VARCHAR。
类型¶
Note
目标:在本节结束时,应已向 estate_property 表添加几个基本字段:
$ psql -d rd-demo
rd-demo=# \d estate_property;
Table "public.estate_property"
Column | Type | Collation | Nullable | Default
--------------------+-----------------------------+-----------+----------+---------------------------------------------
id | integer | | not null | nextval('estate_property_id_seq'::regclass)
create_uid | integer | | |
create_date | timestamp without time zone | | |
write_uid | integer | | |
write_date | timestamp without time zone | | |
name | character varying | | |
description | text | | |
postcode | character varying | | |
date_availability | date | | |
expected_price | double precision | | |
selling_price | double precision | | |
bedrooms | integer | | |
living_area | integer | | |
facades | integer | | |
garage | boolean | | |
garden | boolean | | |
garden_area | integer | | |
garden_orientation | character varying | | |
Indexes:
"estate_property_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"estate_property_create_uid_fkey" FOREIGN KEY (create_uid) REFERENCES res_users(id) ON DELETE SET NULL
"estate_property_write_uid_fkey" FOREIGN KEY (write_uid) REFERENCES res_users(id) ON DELETE SET NULL
字段有两大类别:“简单”字段,即直接存储在模型表中的原子值;“关系”字段,即链接记录(相同或不同模型的记录)的字段。
简单字段的例子有 Boolean、Float、Char、Text、Date 和 Selection。
Exercise
向房地产物业表添加基本字段。
在表中添加以下基本字段:
字段 |
类型 |
|---|---|
name |
字符型 |
description |
文本 |
postcode |
字符型 |
date_availability |
日期 |
expected_price |
浮动 |
selling_price |
浮动 |
bedrooms |
整数 |
living_area |
整数 |
facades |
整数 |
garage |
布尔值 |
garden |
布尔值 |
garden_area |
整数 |
garden_orientation |
选择 |
garden_orientation 字段必须有 4 个可能的值:’North’、’South’、’East’ 和 ‘West’。选择列表定义为元组列表,示例见 此处。
将字段添加到模型后,使用 -u estate 重启服务器
$ ./odoo-bin --addons-path=addons,../enterprise/,../tutorials/ -d rd-demo -u estate
连接到 psql 并检查 estate_property 表的结构。您会注意到表中还添加了几个额外的字段。我们稍后会重新审视它们。
通用属性¶
Note
目标:在本节结束时,estate_property 表中的 name 和 expected_price 列应为非空(not nullable):
rd-demo=# \d estate_property;
Table "public.estate_property"
Column | Type | Collation | Nullable | Default
--------------------+-----------------------------+-----------+----------+---------------------------------------------
...
name | character varying | | not null |
...
expected_price | double precision | | not null |
...
与模型本身一样,字段也可以通过传递配置属性作为参数来进行配置:
name = fields.Char(required=True)
有些属性可用于所有字段,以下是最常用的几种:
string(str,默认值:字段名)字段在界面中的标签(用户可见)。
required(bool,默认值:False)如果为
True,则该字段不能为空。它必须有默认值,或者在创建记录时始终被赋予一个值。help(str,默认值:'')在界面中为用户提供详细的帮助提示信息。
index(bool,默认值:False)请求 Odoo 在该列上创建 数据库索引 。
Exercise
为现有字段设置属性。
添加以下属性:
字段 |
属性 |
|---|---|
name |
required |
expected_price |
required |
重启服务器后,这两个字段应为非空。
自动字段¶
参考:与此主题相关的文档可在 自动字段 中找到。
您可能已经注意到,您的模型中有一些您从未定义的字段。Odoo 会在所有模型中创建一些字段1。这些字段由系统管理,不能写入,但在有用或必要时可以读取:
- 记录标识:
id(Id) 模型中某条记录的唯一标识符。
- 创建日期:
create_date(Datetime) 记录的创建日期。
- 创建用户:
create_uid(Many2one) 创建该记录的用户。
- 修改日期:
write_date(Datetime) 记录的最后修改日期。
- 修改用户:
write_uid(Many2one) 最后修改该记录的用户。
现在我们已经创建了第一个模型,让我们 添加一些安全设置 吧!
- 1
可以 禁用某些字段的自动创建
- 2
可以直接编写原生 SQL 查询,但需要谨慎,因为这会绕过所有 Odoo 身份验证和安全机制。