第六章 该显示UI的部分了
现在我们创建了新的模型和它相关的存取权限,是时候跟用户接口交互了。
在这一章的最后,我们将新建一组菜单去访问list和form视图。
Data Files (XML)
参考:关于这个主题的文档在这里 Data Files.
在第五章中我们新增了一个CSV文件,CSV格式的文件用来存储简单格式的文件是比较合适的。数据格式比较复杂的时候,(比如当加载一个视图的结构或者email模板),我们使用XML格式的文件,例如,这个帮助字段 help field包含了HTML tags,用CSV文件加载将比用XML更方便。
XML文件必须放在跟CSV文件同一目录下,并且需要在清单文件__manifest__.py
中被定义。数据文件的内容在模块安装或者升级的时候会顺序的被加载。因此,针对CSV文件的备注对XML文件都适用。 当数据文件指向视图(view),我们将它们放在views目录中。
这一章我们将通过XML文件加载第一个动作和菜单,动作和菜单是数据库中的标准记录。
注意:
当性能很重要的时候,CSV格式比XML格式的文件更合适,这是因为Odoo加载csv文件比加载Xml文件更快。
在Odoo中,用户接口(动作,菜单,视图)在XML文件中通过新增和组合records被大量定义。通用的模式的是: 菜单>动作>视图。
为了访问记录,用户通过几个菜单级别导航,最深层的菜单是一个动作,它将触发打开一个记录集。
动作(Actions)
参考:关于这个主题的文档在这里 Actions.
目标: 在这一章节最后,系统将会加载一个动作,我们看不到任何用户界面,但是log中应该显示加载文件
INFO rd-demo odoo.modules.loading: loading estate/views/estate_property_views.xml
动作可以通过三种方式触发:
- 通过点击菜单(连接到指定的动作)
- 点击视图中的按钮
- 作为对象的上下文操作
这一章我们只覆盖第一种情况,第二种将在后续的章节中被提到,最后一种作为高级主题来关注。 在我们的房地产例子中,我们将一个菜单链接到estate.property
模型,这样我们可以创建新的记录, 动作可以被看做链接菜单和模型的纽带。
一个关于test.model的基本的动作定义:
<record id="test_model_action" model="ir.actions.act_window">
<field name="name">Test action</field>
<field name="res_model">test.model</field>
<field name="view_mode">tree,form</field>
</record>
id
是一个外部标识符,它可以引用这条记录而不必知道数据库中的记录。model
有一个固定的值ir.actions.act_window
(Window Actions (ir.actions.act_window)).name
动作的名字res_model
动作指向的模型view_mode
可用的视图,在这里是指list和form视图,我们将在后面看到其他的视图类型。
在odoo中,这行的例子比比皆是,不过这里 this 有一个简单动作的例子,注意XML文件的结构,因为你将在接下来的练习中用到它。
练习:
增加一个动作。
在合适的目录中创建estate_property_views.xml,并且定义在清单文件中。
为estate.property
模型创建一个动作。
重启服务你将看到在log中文件被加载。
菜单Menus
参考:关于这个主题的文档在这里 Shortcuts.
目标: 在这一小节的最后,要创建三个菜单并且显示默认的菜单。
为了简化声明菜单(ir.ui.menu)的复杂性,并把它连接到对应的动作,我们使用快捷方式
一个基本的菜单:test_model_action
<menuitem id="test_model_menu_action" action="test_model_action"/>
菜单test_model_menu_action 连接到动作test_model_action, 动作连接到模型test.model,就像之前提到的,动作可以看成连接菜单和模型的纽带。
However, menus always follow an architecture, and in practice there are three levels of menus:
总的来说,菜单总是遵循一定的结构,实际上有三种层次的菜单:
- 根菜单,显示在App菜单中,它是一个下拉菜单
- 第一层菜单,在顶部栏显示
- 动作菜单
定义菜单结构最简单的方式是在XML文件中,下面是一个例子:
<menuitem id="test_menu_root" name="Test">
<menuitem id="test_first_level_menu" name="First Level">
<menuitem id="test_model_menu_action" action="test_model_action"/>
</menuitem>
</menuitem>
第三级菜单的名字会引用在动作中定义的名字。
练习: 增加菜单
新增estate_menus.xml在合适的目录中,并在清单文件中定义。记住加载数据文件的顺序;-)
给estate.property
模型新建三层菜单结构, 完成之前定的目标。
重启服务并刷新浏览器,你将会看到菜单,甚至你可以创建你的第一条房地产广告记录。
字段,属性和视图 (Fields, Attributes And View)
目标: 这一章节最后 selling price 应该设为只读,bedrooms 和availability date 应该有默认值 ,另外,当记录被复制的时候selling price 和 availability date 的值不应该被复制。
给estate.property 模型增加保留字段active
and state
到目前为止,我们的房地产模块只用到了基本的视图,但是很多情况下我们希望微调视图,Odoo中有很多调整视图的方法,通常第一步是确认:
- 默认值
- 有些字段是只读的
- 当记录被复制的时候有些字段的值不能被copy
在我们的房地产模块中,我们希望做到下面的内容:
- selling price 应该设为只读,(后面会自动填充)
- 当记录被复制的时候selling price 和 availability date 的值不应该被复制。
- bedrooms 默认值是 2
- availability date默认值是三个月之内
一些新的属性
进一步学习视图设计之前,让我们回到模型的定义中,我们看到有些属性,比如required=True 影响数据库中表的设计模式,其他的一些属性将会影响视图或者提供默认值。
练习: 给字段增加新的属性
找到合适的属性 (see Field
) to:
- selling price 设置为只读
- 阻止复制 availability date 和 selling price 的值
重启服务并刷新浏览器,你不能设置任何selling prices,当复制一条记录的时候availability date 应该是空的。
默认值
任何字段都可以给一个默认值,在字段定义中,增加选项default=x ,其中x要么是一个python的文字值(布尔,整数,浮点数,字符串)或者是一个有返回值的函数。
name = fields.Char(default="Unknown")
last_seen = fields.Datetime("Last Seen", default=lambda self: fields.Datetime.now())
The name
field will have the value ‘Unknown’ by default while the last_seen
field will be set as the current time.
练习:设置默认值
增加合适的默认值:
- bedrooms 默认值是 2
- availability date 默认值是3个月以内 参考
today()
检查默认值是否像期待的那样。
保留字段(Reserved Fields)
参考:关于这个主题的文档在这里 Shortcuts. Reserved Field names.
A few field names are reserved for pre-defined behaviors. They should be defined on a model when the related behavior is desired.
有几个保留的字段名称已经预先定义好了行为,当相关的行为被需要的时候,他们应该在模型中定义。
练习: 增加active字段
estate.property 增加active字段
重启服务,新建一条新的房屋信息,然后返回list视图。 会发现列表视图中没有出现这条记录。 active是一个保留字段有一个指定的行为,当一条记录的active=false, 它将自动的不会被检索到。 为了显示这条记录,你需要指定搜索不活跃(inactive)的记录
练习
给active字段设置默认值
设置合适的默认值,让记录不在隐藏。
注意: 默认值active=False 将会赋值给所有存在的记录。
练习: 增加state 字段
给estate.property模型增加state字段, 有五种可能的值, “新订单”,“收到订单”,“接受订单”,“已卖出”,“已取消”,这不能为空,也不能被复制,默认值是“新订单”
确认用合适的类型
state 后面会在几个改进的UI中被用到。
现在我们可以和UI交互了,通过默认的视图。 下一步是很明显,我们需要定义自己的视图 our own views.
刷新是必要的,因为性能原因,浏览器缓存了不同类型的菜单和视图。
关于字段的一些通用属性
- string
- help
- invisible
- readonly
- index
- copy