一些用户界面

数据文件 (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.

动作可以通过三种方式触发 :

  1. 点击菜单项目(链接接到指定动作)
  2. 点击视图按钮(如果与action关联)
  3. 对象的上下文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_actionaction链接到model test.model。正如前面所述, action可以看做是菜单和model之间的连接。

注意:这里的id的值和action的值不能设置成一样,否则会报错。

然而,菜单总是遵循一种体系结构,实际上有三个层次的菜单:

  1. 根菜单,显示在App切换器中(Odoo社区版切换器是一个下拉菜单)
  2. 第一级菜单,显示在顶部栏中
  3. 动作菜单

最容易的方式是在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.pyEstateProperty类属性expected_priceselling_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.pyEstateProperty类属性bedroomsselling_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.pyEstateProperty类,增加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, SoldCanceled。必选字段,且不能被拷贝,默认值New

修改 odoo14\custom\estate\models\estate_property.pyEstateProperty类,修改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 开发入门教程系列-一些用户界面的更多相关文章

  1. 移动H5开发入门教程:12点webAPP前端开发经验

    如果你是一名移动H5前端开发人员,25学堂的小编认为下面的分享的12点webAPP前端开发经验是你必须掌握的基础知识点.算是一篇移动H5开发入门教程吧! 1. viewport:也就是可视区域.对于桌 ...

  2. WPF入门教程系列(一) 创建你的第一个WPF项目

    WPF入门教程系列(一) 创建你的第一个WPF项目 WPF基础知识 快速学习绝不是从零学起的,良好的基础是快速入手的关键,下面先为大家摞列以下自己总结的学习WPF的几点基础知识: 1) C#基础语法知 ...

  3. Android Studio JNI开发入门教程

    Android Studio JNI开发入门教程 2016-08-29 14:38 3269人阅读 评论(0) 收藏 举报  分类: JNI(3)    目录(?)[+]   概述 在Andorid ...

  4. SeaJS入门教程系列之使用SeaJS(二)

    SeaJS入门教程系列之使用SeaJS(二) 作者: 字体:[增加 减小] 类型:转载 时间:2014-03-03我要评论 这篇文章主要介绍了SeaJS入门教程系列之使用SeaJS,着重介绍了SeaJ ...

  5. C#,ArcGIS Engine开发入门教程

    C#,ArcGIS Engine开发入门教程 转自:http://blog.csdn.net/yanleigis/article/details/2233674  目录(?)[+] 五实现 一 加载A ...

  6. Silverlight,Windows 8应用开发实例教程系列汇总

    Kevin Fan分享开发经验,记录开发点滴 Silverlight,Windows 8应用开发实例教程系列汇总 2012-06-18 01:05 by jv9, 2145 阅读, 3 评论, 收藏, ...

  7. ActiveMQ详细入门教程系列(一)

    一.什么是消息中间件 两个系统或两个客户端之间进行消息传送,利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成.通过提供消息传递和消息排队模型,它可以在分布式环境下 ...

  8. WPF入门教程系列二十三——DataGrid示例(三)

    DataGrid的选择模式 默认情况下,DataGrid 的选择模式为“全行选择”,并且可以同时选择多行(如下图所示),我们可以通过SelectionMode 和SelectionUnit 属性来修改 ...

  9. WPF入门教程系列三——Application介绍(续)

    接上文WPF入门教程系列二——Application介绍,我们继续来学习Application 三.WPF应用程序的关闭 WPF应用程序的关闭只有在应用程序的 Shutdown 方法被调用时,应用程序 ...

  10. WPF入门教程系列二——Application介绍

    一.Application介绍 WPF和WinForm 很相似, WPF与WinForm一样有一个 Application对象来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只 ...

随机推荐

  1. 新centos6 静态ip 放行端口 hosts主机名 jdk环境变量

    0 jdk 环境变量 vi  /etc/profile source /etc/profile 刷新环境变量 在尾部增加如下代码: #JDK全局环境变量配置export JAVA_HOME=/usr/ ...

  2. linux 中的errno 和 strerror(errno)

    1. errno.h 中包含 errno 这个错误保存值 string.h 包含 strerror() 函数 ,它的原型 是 char *strerror(int errnum); 输入值应该是err ...

  3. token能放在cookie中吗

    能. token一般是用来判断用户是否登录的, 它内部包含的信息有: uid(用户唯一的身份标识). time(当前时间的时间戳). sign(签名,token 的前几位以哈希算法压缩成的一定长度的十 ...

  4. PHP Redis - 事务

    Redis 事务可以一次执行多个命令, 并有两个重要的保证: ① 事务是一个单独的隔离操作:事务中的所有命令都会序列化.按顺序地执行.事务在执行的过程中,不会被其他客户端发送来的命令请求所打断. ② ...

  5. python Elementtree 生成带缩进格式的xml文件

    示例 之前拿ET写xml,直接对root节点调用write函数,会出现产生的xml字符串没有缩进,是干巴巴的一行,可读性比较差,就像下面这样: <annotation><filena ...

  6. python-sqlite数据库锁定

    sqlite3.OperationalError: database is locked  因为sqlite只支持单线程操作,如果此时打开数据库就会出现这个问题

  7. MyBatis-Plus使用SQL语句

    项目中碰到一个必须要使用动态SQL的地方, 想着在xml文件中进行一层一层的判断太麻烦了,也不好理解,要是能在Java代码中组织好SQL,进行查询操作 QueryWrapper<object&g ...

  8. 如何设置表格的高度 element 的table 组件

    <el-table :row-style="{ height: '30px' }" :cell-style="{ padding: 0 }" :data= ...

  9. commons-lang3

    字符串的处理类(StringUtils) //判断是否为空(注:isBlank与isEmpty 区别) StringUtils.isBlank(null);StringUtils.isBlank(&q ...

  10. 三种遍历的方法(map和forEach的区别)

    一. for循环 arr[index]可以改变原数组 二. forEach方法 forEach方法的返回值是一个undefined: 2. 在循环体内改变item的值不会影响原数组,而是只在循环体内生 ...