我们的房地产模块现在从商业角度来看是有意义的。我们创建了特定的视图,添加了几个操作按钮和约束。然而,我们的用户界面仍然有点粗糙。我们希望为列表视图添加一些颜色,并使一些字段和按钮有条件地消失。例如,当房产已出售或取消时,“已售出”和“取消”按钮应消失,因为此时不再允许更改状态。
参考: 文档关联的主题可以查看 Views.
在房地产模块中,我们为房产添加了一个报价列表。我们通过以下代码简单地添加了offer_ids
字段:
该字段使用estate.properties.offer
的特定视图。在某些情况下,我们希望定义一个仅在表单视图上下文中使用的特定列表视图。例如,我们希望显示链接到房产类型的房产列表。然而,为了清楚起见,我们只想显示3个字段:名称、预期价格和状态。
为此,我们可以定义内联列表视图。内联列表视图直接在表单视图中定义。例如:
from odoo import fields, models
class TestModel(models.Model):
_name = "test.model"
_description = "Test Model"
description = fields.Char()
line_ids = fields.One2many("test.model.line", "model_id")
class TestModelLine(models.Model):
_name = "test.model.line"
_description = "Test Model Line"
model_id = fields.Many2one("test.model")
field_1 = fields.Char()
field_2 = fields.Char()
field_3 = fields.Char()
在test.model
的表单视图中,我们使用 field_1
和field_2
为 test.model.line
定义了列表视图
一个简单的示例
event.tag.category.view.form
event.tag.category
修改odoo14\custom\estate\models\estate_property_type.py
property_ids = fields.One2many('estate.property', 'property_type_id')
修改odoo14\custom\estate\views\estate_property_type_views.xml
,添加estate_property_type_view_form
estate.property.type.form
estate.property.type
重启服务,验证效果
参考: 查看本节主题关联文档Field Widgets.
每当我们将字段添加到模型中时,我们(几乎)从来不用担心这些字段在用户界面中会是什么样子。例如,为Date
字段提供的日期选择器,One2many
字段自动显示为列表。Odoo根据字段类型选择正确的“widget”。
然而,在某些情况下,我们需要某个字段的特定表示,这种特定表示的实现,归功于widget
属性。在使用widget=“many2many_tags”
属性时,我们已经将其用于tag_ids
字段。如果我们没有使用它,那么该字段将显示为列表。
每个字段类型都有一系列组件,可用于微调其显示。一些组件也有额外的选项。在Field Widgets中可以找到详尽的列表。
使用 statusbar
组件来展示的 estate.property
的state
,如下图:
提示: 一个简单的示例.
警告
相同字段,只能在列表或表单视图中只添加一次,不支持多次添加。
同一个字段,如果展示多次,会以最后一次的样式统一展示。
编辑odoo14\custom\estate\views\estate_property_views.xml
修改estate_property_view_form
表单视图的
元素
去掉
元素中的state
字段
注意:如果不去掉上述代码,这里的样式将会覆盖statusbar
的state
字段样式,如下:
说明:statusbar_visible
属性值为state
字段可选值(字段值的selection
列表中二元组、单元组中的value
,即元组第一个元素)字符串列表,控制状态栏显示那些状态,如果statusbar_visible
值不为空字符串,则仅显示位于statusbar_visible
属性值中指定的状态,以及视图归属模型中对应字段(例中为state
)的default
属性指定的状态(不管默认值是否在statusbar_visible
属性值中),否则展示全部状态。此外,属性值在视图中的展示顺序,取决于字段可选值在public.ir_model_fields_selection
表中对应sequence
字段值大小,按该字段大小从左到右升序排序属性值
刷新浏览器,验证效果:
参考: 本节主题关联文档Models.
在前面的练习中,我们创建了几个列表视图。然而,我们没有指定默认情况下记录必须按哪个顺序展示。对于许多业务案例来说,这是一件非常重要的事情。例如,在我们的房地产模块中,我们希望在列表顶部显示最高报价
odoo提供了几种设置默认顺序的方法。最常见的方法是直接在模型中定义_order
属性。这样,检索到的记录将遵循确定性顺序,该顺序在所有视图中都是一致的,包括以编程方式搜索记录时。默认情况下,没有指定顺序,因此将根据不确定的顺序检索记录,取决于PostgreSQL。
_order
属性接收一个字符串,该字符串包含将用于排序的字段列表。它将转换为SQL中的order_by子句。例如:
from odoo import fields, models
class TestModel(models.Model):
_name = "test.model"
_description = "Test Model"
_order = "id desc"
description = fields.Char()
如上,记录将按id
降序排序,意味着最高的排在最上面。
练习--添加模型排序
在对应模型中添加一下排序
Model | Order |
---|---|
estate.property |
按 ID降序 |
estate.property.offer |
按Price降序 |
estate.property.tag |
Name |
estate.property.type |
Name |
此处练习比较简单,我就不贴实践代码了,参考上述示例
重启服务,验证效果
可以在模型级别进行排序,它有个优点,即即在检索记录列表的任何地方都有一致的顺序。也可以通过default_order
直接在视图中定义指定排序顺序 (示例)。
crm.activity.report.tree
crm.activity.report
模型排序和视图排序都允许在排序记录时具有灵活性,但仍有一种情况需要考虑:手动排序。用户可能希望根据业务逻辑对记录进行排序。例如,在我们的房地产模块中,我们希望手动对房产类型进行排序。将最常用的类型显示在列表的顶部确实很有用。如果我们的房地产经纪公司主要销售房子,那么在“公寓(Apartment)”之前出现“房子(House)”会更方便。
为此,将sequence
字段与handle
组件结合使用。显然,sequence
字段必须是_order
属性中的第一个字段。
练习--添加手工排序
Model | Field | Type |
---|---|---|
estate.property.type |
Sequence | Integer |
sequence
到 estate.property.type
列表视图提示: 可在 model 和view中查找示例。
sequence = fields.Integer('Sequence', default=1, help="Used to order stages. Lower is better.")
crm.stage.tree
crm.stage
修改odoo14\custom\estate\models\estate_property_type.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from odoo import models, fields
class EstatePropertyType(models.Model):
_name = 'estate.property.type'
_description = 'estate property type'
_order = 'sequence,name'
name = fields.Char(string='name', required=True)
property_ids = fields.One2many('estate.property', 'property_type_id')
sequence = fields.Integer('Sequence', default=1, help="Used to order type")
_sql_constraints = [('check_name', 'unique(name)', 'Type name must be unique !')]
修改odoo14\custom\estate\views\estate_property_type_views.xml
中estate_property_type_view_tree
estate.property.type.tree
estate.property.type
重启服务,验证效果(可手工拖动记录排序)
详细说明所有允许对视图外观进行微调的可用特性是令人望而却步的。因此,我们将挑选最常见的特性进行说明。
目标: 本节末尾中,地产表单视图将拥有以下:
- 有条件的显示按钮和字段
- 标签颜色
预期效果动画地址:https://www.odoo.com/documentation/14.0/zh_CN/_images/form.gif
在我们的房地产模块中,我们希望修改某些字段的行为。例如,我们不希望能够从表单视图创建或编辑房产类型。相反,我们希望在其相应的菜单中处理类型。我们还想给标签增加一种颜色。为了添加这些定制化行为,我们可以将options
属性添加到几个字段组件中。
property_type_id
字段,避免在房产表单视图中创建活编辑房产类型。查看Many2one组件文档 获取更多信息Model | Field | Type |
---|---|---|
estate.property.tag |
Color | Integer |
然后添加合适的选项到 tag_ids
字段以便在标签上添加颜色选择器。查看FieldMany2ManyTags组件文档 获取更多详细信息
编辑odoo14\custom\estate\models\estate_property.py
修改
property_type_id = fields.Many2one("estate.property.type", string="PropertyType")
为
property_type_id = fields.Many2one("estate.property.type", string="PropertyType", options="{'no_create_edit': True}")
重启服务,验证效果
如下,看不到创建和编辑入口了
编辑odoo14\custom\estate\models\estate_property_tag.py
,新增color
字段:
color = fields.Integer(string='Color')
修改odoo14\custom\estate\views\estate_property_views.xml
estate_property_view_form
中
为
重启服务,验证效果
在"一些用户界面"章节中,我们看到保留字段用于特定行为。例如,active
字段用于自动筛选出非活动记录。我们还添加了state
作为保留字段。现在是使用它的时候了!state
字段与视图中的states
属性结合使用,以有条件地显示按钮。
使用states
属性来显示有条件的显示头部按钮,如本节目标中所述(注意修改状态时“已售出”和“取消”按钮的变化)
提示: 请不要犹豫在Odoo XML文件中搜索states=
以获得一些示例
修改odoo14\custom\estate\views\estate_property_views.xml
表单视图中的
说明:
第一个按钮的states
配置,意为仅在当前记录state
的值Offer Accepted
时显示该按钮
第一个按钮的states
配置,意为仅在当前记录state
的值New
、Offer Received
、Offer Accepted
时显示该按钮
刷新浏览器验证(可通过修改数据库中对应记录的state
值来观察按钮的显示变化)
更普遍的,多亏attrs
属性,可以根据其他字段的值使字谋个字段 不可见(invisible
)、只读(readonly
)或必需(required
。注意, invisible
也可以应用于视图的其他元素,如按钮( button
)或组( group
)。
attrs
为一个以属性为key,以domain
为值的字典。 domain
给出了应用该属性的条件。例如:
这意味着当 is_partner
为 False
时description
字段不可见。需要注意的是,attrs
中使用的字段必须出现在视图中。如果它不应该显示给用户,我们可以使用invisible
属性来隐藏它。
attrs
estate.property
表单视图中的花园面积(garden area)和朝向(garden orientation)不可见Offer Accepted
, Sold
或 Canceled
时,不允许添加报价。为此使用readonly
attrs
.警告
在视图中使用(条件)
readonly
属性可能有助于防止数据输入错误,但请记住,它不会提供任何级别的安全性!服务器端没有进行检查,因此始终可以通过RPC调用在字段上进行写入。
修改odoo14\custom\estate\views\estate_property_views.xml
表单视图
修改offer_ids
属性
说明: in
表示在列表中,反之使用 not in
修改odoo14\custom\estate\views\estate_property_offer_views.xml
给button
新增属性
刷新浏览器,验证效果
当模型只有几个字段时,可以通过列表视图直接编辑记录,而不必打开表单视图。在房地产示例中,不需要打开窗体视图来添加报价或创建新标签。这可以通过editable
属性实现。
练习--使列表视图可编辑
让estate.properties.offer
和estate.properties.tag
列表视图可编辑。
此外,当一个模型有很多字段时,很可能会在列表视图中添加太多字段,使其变得不清晰。另一种方法是添加字段,并让这些字段可以有选择的被隐藏。这可以通过optional
属性实现。
练习-使字段成为可选字段
默认情况下,将estate.properties
列表视图中的字段date_availability
设置为可选,默认隐藏。
修改odoo14\custom\estate\views\estate_property_offer_views.xml
中的tree
视图中的
元素,增加editable
属性:
刷新浏览器查看
修改odoo14\custom\estate\views\estate_property_views.xml
estate_property_view_tree
中的
元素
说明:
editable="value"
,其中value
可选值为top|bottom
,表示点击创建记录时,待创建记录出现在列表的顶部(value=top
)还是底部(value=bottom
)。optional="value"
,value
可选值为hide
(隐藏),show
(显示)刷新浏览器验证
最后,颜色代码有助于直观地强调记录。例如,在房地产模块中,我们希望以红色显示拒绝的报价,以绿色显示接受的报价。这可以通过 decoration-{$name}
属性实现(有关完整列表,请参阅 decorations):
is_partner
为True
的记录将显示为绿色。
练习--添加一些装饰
在 estate.property
列表视图中:
muted
)修改odoo14\custom\estate\views\estate_property_views.xml
,给列表视图
元素增加decoration-x
属性:
刷新浏览器验证
Reference: 查看主题关联文档Search 和 Search defaults
本章目标:在本节结束时,默认情况下将过滤可用的属性,搜索居住区域将返回面积大于给定数字的结果。
预期效果动画地址:https://www.odoo.com/documentation/14.0/zh_CN/_images/search.gif
最后但并非最不重要的是,我们希望在搜索时应用一些调整。首先,我们希望在访问房产列表时默认应用“Avaliable”筛选器。为了实现这一点,我们需要使用search_default_{$name}
操作上下文,其中{$name}
为过滤器名称,即搜索视图中定义的
、
元素的name
属性值。这意味着我们可以在操作级别定义默认激活的过滤器。
这里是一个带有 相应过滤器的操作 示例。
crm.lead.search
crm.lead
32
...
...
Pipeline Analysis
crm.lead
pivot,graph,tree,form
{'search_default_opportunity': True, 'search_default_current': True}
...
在estate.properties
action
中,默认选择‘Available’筛选器。
修改odoo14\custom\estate\views\estate_property_views.xml
link_estate_property_action
Properties
estate.property
tree,form
{'search_default_state': True}
重启服务,刷新浏览器验证
我们模块的另一个有用的改进是能够按居住面积高效搜索。实际上,用户需要搜索“至少”给定面积的房产。期望用户能够找到一个精确居住面积的房产是不现实的。总是可以进行自定义搜索,但这很不方便。
搜索视图的
元素可以包含一个filter_domain
,它会覆盖为搜索给定字段而生成的domain
。在给定domain
中,self
表示用户输入的值。在下面的示例中,它用于搜索 name
和 description
字段。
添加一个 filter_domain
到居住面积,以搜索面积大于等于给值的房产。
修改odoo14\custom\estate\views\estate_property_views.xml
estate_property_search_view
,增加living_area
字段
重启服务,刷新页面后验证
在本节的末尾,房产类型表单视图上会有一个统计按钮,当单击该按钮时,它会显示与给定类型的房产相关的所有报价的列表。
预期效果动画地址:https://www.odoo.com/documentation/14.0/zh_CN/_images/stat_button.gif
在我们的房地产模块中,我们希望快速链接到与给定房产类型相关的报价,正如目标描述中展示的那样。
提示:通过在Odoo代码库中查找“oe_stat_button”,以获取一些示例。
本次练习将引入Related fields的概念。理解它的最简单方法是将其视为计算的字段的特殊情况。以下description
字段的定义:
...
partner_id = fields.Many2one("res.partner", string="Partner")
description = fields.Char(related="partner_id.name")
等价于:
...
partner_id = fields.Many2one("res.partner", string="Partner")
description = fields.Char(compute="_compute_description")
@api.depends("partner_id.name")
def _compute_description(self):
for record in self:
record.description = record.partner_id.name
每当partner
的name
改变时,description
也会被改变。
property_type_id
到estate.property.offer
。 我们可以将其定义为property_id.property_type_id
上的关联字段,并将其设置为存储。因为此字段,报价将在创建时链接到房产类型。您可以将该字段添加到报价列表视图中,以确保其正常工作。.
offer_ids
到estate.property.type
,该字段为前面步骤定义的字段的One2many
inverse
offer_count
到 estate.property.type
。该字段为一个计算的字段,用于统计给定房产类型的报价的数量 (使用offer_ids
进行计算)。此时,你已经掌握了了解有多少报价链接到一个房产类型的所有必要的信息。如果有疑问,请将offer_ids
和offer_count
直接添加到视图中。下一步是在单击统计按钮时显示列表。
estate.properties.type
上创建一个统计按钮,指向estate.property.offer
action。这意味着你应该使用type=“action”
属性此时,点击统计按钮,应该显示所有报价。我们仍然需要过滤的报价。
在 estate.property.offer
action中添加一个domain
, 将 property_type_id
定义为等于active_id
(=当前记录, 这里是一个示例)
event.registration
Attendees
kanban,tree,form,calendar,graph
[('event_id', '=', active_id)]
...
编辑odoo14\custom\estate\models\estate_property_offer.py
,修改
from odoo import models, fields
为
from odoo import models, fields, api
新增以下字段:
property_type_id = fields.Many2one(related="property_id.property_type_id", store=True)
修改odoo14\custom\estate\models\estate_property_type.py
,新增offer_ids
,offer_count
字段,新增_compute_offer_count
函数
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from odoo import models, fields, api
class EstatePropertyType(models.Model):
_name = 'estate.property.type'
_description = 'estate property type'
_order = 'sequence, name'
sequence = fields.Integer('Sequence', default=1, help="Used to order type")
name = fields.Char(string='name', required=True)
property_ids = fields.One2many('estate.property', 'property_type_id')
offer_ids = fields.One2many('estate.property.offer', 'property_type_id')
offer_count = fields.Integer(compute='_compute_offer_count')
_sql_constraints = [('check_name', 'unique(name)', 'Type name must be unique !')]
@api.depends('offer_ids.price')
def _compute_offer_count(self):
for record in self:
record.offer_count = sum(record.mapped('offer_ids.price'))
修改odoo14\custom\estate\views\estate_property_type_views.xml
,新增display_offers_for_given_estate_property_action
,button_box
div
元素
Property Types
estate.property.type
tree,form
Property Offers
ir.actions.act_window
estate.property.offer
tree
[('property_type_id', '=', active_id)]
{'default_event_id': active_id}
estate.property.type.tree
estate.property.type
estate.property.type.form
estate.property.type
重启服务,刷新浏览器验证
通过按钮跳转后带来的问题
点击浏览器回退键,面包屑显重复显示了,如下,暂时未找到解决方案