odoo 开发入门教程系列-一些用户界面
一些用户界面
数据文件 (XML)
参考: 该主题关联文档可以查看Data Files.
上一章,我们通过CSV文件添加了数据。当需要添加数据格式简单时,用CSV格式还是很方便的,当数据格式更复杂时(比如视图架构或者一个邮件模板),我们使用XML格式。比如包含HTML tags的 help field。虽然可以通过CSV文件加载这样的数据,但是使用XML更方便。
类似CSV文件,XML文件也必须按约定添加到合适的目录,并在 __manifest__.py
中进行定义。数据文件中的内容也是在模块安装或者更新时按序加载。因此,对CSV文件所做的所有说明对XML文件都适用。当数据链接到视图时,我们将它们添加到views
文件夹中
本章,我们将通过XML文件加载我们第一个action和菜单。Actions 和菜单为数据库中的标准记录。
注解:
当程序很注重性能时,CSV格式优先于XML格式。这是因为,在odoo中加载CSV文件比加载XML文件更快。
odoo中,用户接口(action,菜单和视图)大部分是通过创建和组装XML文件中的记录来定义的。常见的模式为 菜单> action > 视图。为了访问记录,用户在几个菜单级中导航。最深层是触发打开记录列表的action。
操作(Actions)
参考: 主题相关文档可以查看 Actions.
动作可以通过三种方式触发 :
- 点击菜单项目(链接接到指定动作)
- 点击视图按钮(如果与action关联)
- 对象的上下文action
本章仅涵盖第一种情况。 我们Real Estate例子中,希望将一个菜单连接到 estate.property
model, 以便创建一个新记录。 action可以视为菜单和model之间的链接
test.model
的基本action:
<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
action名称res_model
action应用的范围。view_mode
可获取的视图。本例中为列表(树)和表格视图。
odoo中到处都可以找到例子,但是这个 简单action的好例子。关注XML 数据文件结构,因为你在后续的练习中会用到。
<?xml version="1.0"?>
<odoo>
<record id="crm_lost_reason_view_search" model="ir.ui.view">
<field name="name">crm.lost.reason.view.search</field>
<field name="model">crm.lost.reason</field>
<field name="arch" type="xml">
<search string="Search Opportunities">
<field name="name"/>
<filter string="Include archived" name="archived" domain="['|', ('active', '=', True), ('active', '=', False)]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
</search>
</field>
</record>
<record id="crm_lost_reason_view_form" model="ir.ui.view">
<field name="name">crm.lost.reason.form</field>
<field name="model">crm.lost.reason</field>
<field name="arch" type="xml">
<form string="Lost Reason">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_lost_leads" type="object"
class="oe_stat_button" icon="fa-star">
<div class="o_stat_info">
<field name="leads_count" class="o_stat_value"/>
<span class="o_stat_text"> Leads</span>
</div>
</button>
</div>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<div class="oe_title">
<div class="oe_edit_only">
<label for="name"/>
</div>
<h1 class="mb32">
<field name="name" class="mb16"/>
</h1>
<field name="active" invisible="1"/>
</div>
</sheet>
</form>
</field>
</record>
<record id="crm_lost_reason_view_tree" model="ir.ui.view">
<field name="name">crm.lost.reason.tree</field>
<field name="model">crm.lost.reason</field>
<field name="arch" type="xml">
<tree string="Channel" editable="bottom">
<field name="name"/>
</tree>
</field>
</record>
<!-- Configuration/Lead & Opportunities/Lost Reasons Menu -->
<record id="crm_lost_reason_action" model="ir.actions.act_window">
<field name="name">Lost Reasons</field>
<field name="res_model">crm.lost.reason</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Define a new lost reason
</p><p>
Use lost reasons to explain why an opportunity is lost.
</p><p>
Some examples of lost reasons: "We don't have people/skill", "Price too high"
</p>
</field>
</record>
<record id="menu_crm_lost_reason" model="ir.ui.menu">
<field name="action" ref="crm.crm_lost_reason_action"/>
</record>
</odoo>
练习
为 estate.property
model 创建action。
在适当的位置(本例中为odoo14/custom/estate/models/views
)创建 estate_property_views.xml
<?xml version="1.0"?>
<odoo>
<record id="link_estate_property_action" model="ir.actions.act_window">
<field name="name">Properties</field>
<field name="res_model">estate.property</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>
修改odoo14/custom/estate/__manifest__.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
{
'name': 'estate',
'depends': ['base'],
'data':['security/ir.model.access.csv',
'views/estate_property_views.xml'
]
}
重启服务并观察文件加载日志。
菜单(Menus)
参考: 和本主题关联文档可以查看Shortcuts.
为了减少菜单(ir.ui.menu
)定义和链接到对应action的复杂性,我们可以使用 shortcut
test_model_action
一个的基础菜单:
<menuitem id="test_model_menu_action" action="test_model_action"/>
test_model_menu_action
菜单被链接到 test_model_action
,action
链接到model test.model
。正如前面所述, action
可以看做是菜单和model
之间的连接。
注意:这里的id的值和action的值不能设置成一样,否则会报错。
然而,菜单总是遵循一种体系结构,实际上有三个层次的菜单:
- 根菜单,显示在App切换器中(Odoo社区版切换器是一个下拉菜单)
- 第一级菜单,显示在顶部栏中
- 动作菜单
最容易的方式是在XML文件中定义结构来创建菜单。
为 test_model_action
定义的一个基础菜单结构:
<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>
第三级菜单的名称,直接从action
获取,即为action
属性值
练习
添加菜单
在合适的目录(本例中为odoo14/custom/estate/models/views
)创建 estate_menus.xml
文件
<?xml version="1.0"?>
<odoo>
<menuitem id="test_menu_root" name="Test">
<menuitem id="test_first_level_menu" name="First Level">
<menuitem id="estate_property_menu_action" action="link_estate_property_action"/>
</menuitem>
</menuitem>
</odoo>
修改odoo14/custom/estate/__manifest__.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
{
'name': 'estate',
'depends': ['base'],
'data':['security/ir.model.access.csv',
'views/estate_property_views.xml',
'views/estate_menus.xml'
]
}
重启odoo服务,查看效果
字段,属性和视图(Fields, Attributes And View)
到目前为止,我们只对房产广告使用了通用视图,但在大多数情况下,我们希望对视图进行微调。Odoo有许多微调方式,但通常第一步是确保:
- 某些字段有默认值
- 某些字段只读
- 当记录重复时,某些字段不能被拷贝
在我们的房产业务案例中,我们希望::
- 售价只读(往后将自动填充)
- 当记录重复时,可用日期和售价不能被拷贝
- 卧室数量应该默认为2
- 默认可用日期应该为3个月
一些新属性
在进一步进行视图设计之前,让我们回到模型定义。我们看到一些属性,如required=True
,会影响数据库中的表模式。其他属性也将影响视图或提供默认值。
练习 -- 添加一些属性到字段。
查找一些合适的属性 (查看字段
) 来:
- 设置售价为只读
- 阻止复制可用日期和售价
修改 odoo14\custom\estate\models\estate_property.py
中EstateProperty
类属性expected_price
,selling_price
的值如下:
expected_price = fields.Float('expected price', digits=(8, 2), required=True)
selling_price = fields.Float('selling price', digits=(8, 2), readonly=True, copy=False)
重启服务和并刷新浏览器界面,我们可以看到无法设置任何售价。复制记录时,可用日期应为空。
预期效果可参考该动画连接:https://www.odoo.com/documentation/14.0/zh_CN/_images/attribute_and_default.gif
默认值
可以为任何字段设置默认值。字段定义中,添加 default=X
, 其中的X
可以是Python文本值(boolean, integer, float, string) ,也可以是一个以model对象自身为入参并返回一个值的函数:
name = fields.Char(default="Unknown")
last_seen = fields.Datetime("Last Seen", default=lambda self: fields.Datetime.now())
例中name
字段默认值为‘Unknown’,而last_seen
字段默认值为当前时间
练习 -- 设置默认值
添加适当的默认值:
- 卧室数量默认值为 2
- 可用日期默认为3个月内
修改 odoo14\custom\estate\models\estate_property.py
中EstateProperty
类属性bedrooms
,selling_price
的值如下:
bedrooms = fields.Integer(default=2)
date_availability = fields.Datetime('Availability Date', copy=False, default= lambda self: fields.Datetime.today())
重启服务和并刷新浏览器界面验证
保留字段
参考: 主题相关文档可参考 保留字段名称.
odoo为预定义行为保留了一些字段名称。当需要相关行为时,需要在模型中定义这些保留字段。
练习 -- 添加active
字段
添加一个 active
字段到estate.property
模型。
修改 odoo14\custom\estate\models\estate_property.py
中EstateProperty
类,增加active
属性
active = fields.Boolean('Active')
重启服务,刷新浏览器界面,新增一条记录,新增时勾选Active
复选框,即active=True
,验证效果。
预期效果可参考该动画链接:https://www.odoo.com/documentation/14.0/zh_CN/_images/inactive.gif
注意,已存在的记录的active
字段默认值为False
练习--为active
字段添加设置
为active
字段设置默认值
为 active
字段设置适当的属性值,让它不再出现在页面。
练习 -- 添加state
字段
为estate.property
model添加state
字段(字段名可自定义),一个选择列表。可选值: New, Offer Received, Offer Accepted, Sold 和Canceled。必选字段,且不能被拷贝,默认值New
修改 odoo14\custom\estate\models\estate_property.py
中EstateProperty
类,修改active
字段,增加state
字段
active = fields.Boolean('Active', default=True, invisible=True) # 注意:实践发现,invisible字段不起作用
state = fields.Selection(
string='State',
selection=[('New','New'),
('Offer Received','Offer Received'),
('Offer Accepted', 'Offer Accepted'),
('Sold','Sold'),
('Canceled', 'Canceled')],
copy=False
)
重启服务,验证效果
odoo 开发入门教程系列-一些用户界面的更多相关文章
- 移动H5开发入门教程:12点webAPP前端开发经验
如果你是一名移动H5前端开发人员,25学堂的小编认为下面的分享的12点webAPP前端开发经验是你必须掌握的基础知识点.算是一篇移动H5开发入门教程吧! 1. viewport:也就是可视区域.对于桌 ...
- WPF入门教程系列(一) 创建你的第一个WPF项目
WPF入门教程系列(一) 创建你的第一个WPF项目 WPF基础知识 快速学习绝不是从零学起的,良好的基础是快速入手的关键,下面先为大家摞列以下自己总结的学习WPF的几点基础知识: 1) C#基础语法知 ...
- Android Studio JNI开发入门教程
Android Studio JNI开发入门教程 2016-08-29 14:38 3269人阅读 评论(0) 收藏 举报 分类: JNI(3) 目录(?)[+] 概述 在Andorid ...
- SeaJS入门教程系列之使用SeaJS(二)
SeaJS入门教程系列之使用SeaJS(二) 作者: 字体:[增加 减小] 类型:转载 时间:2014-03-03我要评论 这篇文章主要介绍了SeaJS入门教程系列之使用SeaJS,着重介绍了SeaJ ...
- C#,ArcGIS Engine开发入门教程
C#,ArcGIS Engine开发入门教程 转自:http://blog.csdn.net/yanleigis/article/details/2233674 目录(?)[+] 五实现 一 加载A ...
- Silverlight,Windows 8应用开发实例教程系列汇总
Kevin Fan分享开发经验,记录开发点滴 Silverlight,Windows 8应用开发实例教程系列汇总 2012-06-18 01:05 by jv9, 2145 阅读, 3 评论, 收藏, ...
- ActiveMQ详细入门教程系列(一)
一.什么是消息中间件 两个系统或两个客户端之间进行消息传送,利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成.通过提供消息传递和消息排队模型,它可以在分布式环境下 ...
- WPF入门教程系列二十三——DataGrid示例(三)
DataGrid的选择模式 默认情况下,DataGrid 的选择模式为“全行选择”,并且可以同时选择多行(如下图所示),我们可以通过SelectionMode 和SelectionUnit 属性来修改 ...
- WPF入门教程系列三——Application介绍(续)
接上文WPF入门教程系列二——Application介绍,我们继续来学习Application 三.WPF应用程序的关闭 WPF应用程序的关闭只有在应用程序的 Shutdown 方法被调用时,应用程序 ...
- WPF入门教程系列二——Application介绍
一.Application介绍 WPF和WinForm 很相似, WPF与WinForm一样有一个 Application对象来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只 ...
随机推荐
- 新centos6 静态ip 放行端口 hosts主机名 jdk环境变量
0 jdk 环境变量 vi /etc/profile source /etc/profile 刷新环境变量 在尾部增加如下代码: #JDK全局环境变量配置export JAVA_HOME=/usr/ ...
- linux 中的errno 和 strerror(errno)
1. errno.h 中包含 errno 这个错误保存值 string.h 包含 strerror() 函数 ,它的原型 是 char *strerror(int errnum); 输入值应该是err ...
- token能放在cookie中吗
能. token一般是用来判断用户是否登录的, 它内部包含的信息有: uid(用户唯一的身份标识). time(当前时间的时间戳). sign(签名,token 的前几位以哈希算法压缩成的一定长度的十 ...
- PHP Redis - 事务
Redis 事务可以一次执行多个命令, 并有两个重要的保证: ① 事务是一个单独的隔离操作:事务中的所有命令都会序列化.按顺序地执行.事务在执行的过程中,不会被其他客户端发送来的命令请求所打断. ② ...
- python Elementtree 生成带缩进格式的xml文件
示例 之前拿ET写xml,直接对root节点调用write函数,会出现产生的xml字符串没有缩进,是干巴巴的一行,可读性比较差,就像下面这样: <annotation><filena ...
- python-sqlite数据库锁定
sqlite3.OperationalError: database is locked 因为sqlite只支持单线程操作,如果此时打开数据库就会出现这个问题
- MyBatis-Plus使用SQL语句
项目中碰到一个必须要使用动态SQL的地方, 想着在xml文件中进行一层一层的判断太麻烦了,也不好理解,要是能在Java代码中组织好SQL,进行查询操作 QueryWrapper<object&g ...
- 如何设置表格的高度 element 的table 组件
<el-table :row-style="{ height: '30px' }" :cell-style="{ padding: 0 }" :data= ...
- commons-lang3
字符串的处理类(StringUtils) //判断是否为空(注:isBlank与isEmpty 区别) StringUtils.isBlank(null);StringUtils.isBlank(&q ...
- 三种遍历的方法(map和forEach的区别)
一. for循环 arr[index]可以改变原数组 二. forEach方法 forEach方法的返回值是一个undefined: 2. 在循环体内改变item的值不会影响原数组,而是只在循环体内生 ...