08. 界面基础
前面的章节中已经创建了新模型并配置相应的访问权限,这一节我们将学习用户界面交互。在本章中将创建几个菜单,并通过菜单访问默认列表和表单视图。
1、数据文件(XML)
在前面安全简介的章节中,通过 CSV 文件添加了数据。当要加载的数据格式简单时,CSV 格式非常方便。当格式较为复杂时(例如,加载视图或电子邮件模板的结构),也可以使用 XML 格式。例如,帮助字段包含 HTML 标签。虽然可以通过 CSV 文件加载此类数据,但是使用 XML 文件更为便捷。
XML 文件必须与 CSV 文件放置在同一文件夹中,并在 __manifest__.py 中进行类似的定义。当模块安装或更新时,数据文件的内容也会按顺序加载,因此针对 CSV 文件的所有说明同样适用于 XML 文件。当数据与视图相关联时,要将其添加到 views 文件夹中。
在本章中,我们将通过 XML 文件加载第一个操作和菜单。操作和菜单是数据库表中的标准行记录。
注意:一般情况下 CSV 格式比 XML 格式性能更高。在 Odoo 中就是如此,加载 CSV 文件的速度比加载 XML 文件更快。
在 Odoo 中,用户界面(操作、菜单和视图)主要通过创建和组合 XML 文件中定义的记录来实现。一种常见的模式是“菜单 > 操作 > 视图”。用户通过浏览多个菜单层级来访问记录;最深层级是一个操作,该操作会触发记录列表的打开。
2、操作
当系统升级时,系统将自动加载操作,虽然用户界面中目前还看不到任何内容,但日志中应已显示该文件已加载:
INFO odoodb odoo.modules.loading: loading estate/views/estate_property_views.xml操作可以通过以下三种方式触发:
- 点击菜单项(与特定操作相关联)
- 点击视图中的按钮(如果这些按钮与操作相关联)
- 作为对象的上下文操作
本章仅介绍第一种情况。第二种情况将在后续章节中介绍,而最后一种情况则是进阶主题的重点。在estate示例中,将实现一个菜单与 estate.property 模型关联起来,以便能够创建新的记录。该操作可以视为菜单与模型之间的连接。
property_model的基本操作如下:
<record id="property_model_action" model="ir.actions.act_window">
<field name="name">Test action</field>
<field name="res_model">property_model</field>
<field name="view_mode">list,form</field>
</record>以上内容的说明如下:
id是一个外部标识符,它可用于引用记录,无需知道其在数据库中的标识符。model的固定值为ir.actions.act_window,窗口操作 (ir.actions.act_window)。name是操作的名称。res_model是该操作所适用的模型。view_mode指可用的视图;在此示例中,它们是列表视图和表单视图。稍后将看到还有其他视图模式。
在 Odoo 中随处可见此类示例,但这确实是一个简单操作的绝佳范例。需要注意 XML 数据文件的结构,因为在接下来的练习中会用到它。
实践一:添加操作
在相应的文件夹中创建 estate_property_views.xml 文件,并在__manifest__.py 文件中进行定义。为模型 estate.property 创建一个操作。重启服务器后,应该能在日志中看到该文件已被加载。
文件:estate/views/estate_property_views.xml 的代码如下:
3、菜单
在本节结束时,应创建三个菜单,并显示默认视图:



为了简化声明菜单(ir.ui.menu)并将其与相应操作关联的复杂性,可以使用 <menuitem> 快捷方式。
property_model_action 的基本菜单如下:
<menuitem id="property_model_menu_action" action="property_model_action"/>菜单 property_model_menu_action 与操作 property_model_action 相关联,而该操作又与模型 property_model 相关联。如前所述,操作可以被视为菜单与模型之间的纽带。
然而,菜单总是遵循一定的架构,实际上菜单分为三个层次:
- 根菜单,显示在应用切换器中 (Odoo 社区版的应用切换器是一个下拉菜单);
- 一级菜单,显示在顶部栏中;
- 操作菜单;
如下所示:

定义结构最简单的方法是在 XML 文件中创建它。test_model_action 的基本结构如下:
<menuitem id="property_menu_root" name="Test">
<menuitem id="property_first_level_menu" name="First Level">
<menuitem id="property_model_menu_action" action="property_model_action"/>
</menuitem>
</menuitem>添加菜单
在相应的文件夹中创建 estate_menus.xml 文件,并在 __manifest__.py 文件中进行定义。数据文件按顺序加载。为 estate.property 操作创建三级菜单。
重启服务器并刷新浏览器。现在应该能看到菜单了,甚至可以创建第一条房产广告了!
4、字段、属性与视图
在本节末尾,售价应设为只读,卧室数量和可入住日期应具有默认值。此外,在复制记录时,售价和可入住日期的数值将不会被复制。
已将保留字段 active 和 state 添加到 estate.property 模型中。

到目前为止,仅在房地产广告中使用了通用视图,但在大多数情况下,我们需要对视图进行微调。Odoo 中可以进行许多微调,但通常首先是确保:
- 某些字段具有默认值。
- 某些字段为只读。
- 复制记录时,某些字段不会被复制。
代码设计:
class Property(models.Model):
_name = "estate.property"
_description = "房地产模型"
name = fields.Char("标题/名称", required=True, translate=True)
date_availability = fields.Date(string="有效期", default=datetime.now())
expected_price = fields.Float("期望价格", required=True)
selling_price = fields.Float("实际售价", required=True, readonly=True, copy=False)
bedrooms = fields.Integer("房间数量", default=2)
# ... ....一些新属性
在继续进行视图设计之前,让我们先回顾一下模型定义。可以看到某些属性(例如 required=True)会影响数据库中的表结构。而其他属性则会影响视图或提供默认值。
字段添加新属性
查找相应的属性(参见“字段”),以:
- 将销售价格设为只读
- 禁止复制可用日期和销售价格的数值
state = fields.Selection(
string='状态',
selection=[('new', '新建'), ('offer_received', '已收到报价'), ('offer_accepted', '报价已接受'), ('canceled', '取消'), ('sold', '已售出')],
default='new',
readonly=True,
)
active = fields.Boolean(default=True, string="活动")