Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >odoo 开发入门教程系列-基本视图

odoo 开发入门教程系列-基本视图

作者头像
授客
发布于 2023-03-27 01:49:10
发布于 2023-03-27 01:49:10
3.7K00
代码可运行
举报
文章被收录于专栏:授客的专栏授客的专栏
运行总次数:0
代码可运行

在上一章中已经看到,odoo能够为给定模型生成默认视图。实际上,默认视图对于业务应用程序来说是不可接受的。相反,我们至少应该以逻辑的方式组织各个字段。

视图是在带有操作和菜单的XML文件中定义的。它们是ir.ui.view model的实例。

在我们的estate模块中,我们需要以逻辑方式组织字段:

  • 在列表(树)视图中,我们希望显示的不仅仅是名称。
  • 在表单视图中,应该对字段进行分组。
  • 在搜索视图中,我们必须能够搜索的不仅仅是名称。具体来说,我们需要"Available"的地产筛选器和按"postcode"分组的快捷方式

List(列表)

参考: 主题关联文档可参考List.

列表视图,也叫树(tree)视图, 以表格的形式显示记录。

视图根元素为<tree>。其最基础版本仅简单的列出要在表中显示的所有字段(其中每个字段都是一列):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<tree string="Tests">
    <field name="name"/>
    <field name="last_seen"/>
</tree>

练习 -- 添加一个自定义列表视图

在合适的XML文件中为estate.property model定义一个列表视图。 一个简单的示例

修改odoo14/custom/estate/views/estate_property_views.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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>
    
    <!--本小节添加的内容-->
    <record id="estate_property_view_tree" model="ir.ui.view">
        <field name="name">estate.property.tree</field>
        <field name="model">estate.property</field>
        <field name="arch" type="xml">
            <tree string="Tests">
                <field name="name" string="Title"/>
                <field name="postcode" string="Postcode"/>
                <field name="bedrooms" string="Bedrooms"/>
                <field name="living_area" string="Living Area"/>
                <field name="expected_price" string="Expected Price"/>
                <field name="selling_price" string="Selling Price"/>
                <field name="date_availability" string="Avalilable Form"/>
            </tree>
        </field>
    </record>
</odoo>

注意:暂时不要添加示例中的 editable="bottom"属性

说明:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<field name="name">自定义列表名称</field>
<field name="model">模型名称,即_name的值</field>

重启服务,浏览器验证,效果如下:

说明:如果未给<field/>添加string属性,则显示如下:

Form(表单)

参考: 主题关联文档可以查看Form.

表单用于创建和编辑单条件记录,其根元素为 <form>,由高层框架元素(groupnotebook)和交互元素 (按钮和字段):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<form string="Test">
    <sheet>
        <group>
            <group>
                <field name="name"/>
            </group>
            <group>
                <field name="last_seen"/>
            </group>
            <notebook>
                <page string="Description">
                    <field name="description"/>
                </page>
            </notebook>
        </group>
    </sheet>
</form>

可以使用常规HTML标记(如"div"和"h1")以及"class"属性(Odoo提供了一些内置类)来微调外观。

一个简单示例.

练习 -- 添加自定义表单视图

在合适的XML文件中为estate.property 定义视图

为了避免每次修改视图时都重新启动服务器,可以在启动服务器时添加--dev-xml,以便只刷新页面就可以查看视图修改,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python odoo-bin --addons-path=custom,odoo/addons -r myodoo -w test123 -d odoo -u estate --dev xml

修改odoo14/custom/estate/views/estate_property_views.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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>

    <record id="action_lost_leads" 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>

    <record id="estate_property_view_tree" model="ir.ui.view">
        <field name="name">estate.property.tree</field>
        <field name="model">estate.property</field>
        <field name="arch" type="xml">
            <tree string="Tests">
                <field name="name" string="Title"/>
                <field name="postcode" string="Postcode"/>
                <field name="bedrooms" string="Bedrooms"/>
                <field name="living_area" string="Living Area"/>
                <field name="expected_price" string="Expected Price"/>
                <field name="selling_price" string="Selling Price"/>
                <field name="date_availability" string="Avalilable Form"/>
            </tree>
        </field>
    </record>
    
    <!--本小节添加的内容-->
    <record id="estate_property_view_form" model="ir.ui.view">
        <field name="name">estate.property.form</field>
        <field name="model">estate.property</field>
        <field name="arch" type="xml">
            <form string="estate property form">
                <sheet>
                    <h1>
                        <field name="name"/>
                    </h1>
                    <group>
                        <group>
                            <field name="postcode" string="Postcode" ></field>
                            <field name="date_availability" string="Available From"></field>
                        </group>
                        <group>
                            <field name="expected_price" string="Expected Price"></field>
                            <field name="selling_price" string="Selling Price"></field>
                        </group>
                    </group>
                    <notebook>
                        <page string="Description">
                            <group>
                                <field name="description"></field>
                                <field name="bedrooms"></field>
                                <field name="living_area"></field>
                                <field name="facades"></field>
                                <field name="garage"></field>
                                <field name="garden"></field>
                                <field name="garden_area"></field>
                                <field name="garden_orientation"></field>
                            </group>
                        </page>
                    </notebook>
                </sheet>
            </form>
        </field>
    </record>
</odoo>

查看效果

Search(搜索)

参考: 本主题相关文档可参考Search.

搜索视图与列表及表单视图略有不同,因为它们不显示内容。尽管它们适用于特定模型,但它们用于过滤其他视图的内容(通常是聚合视图,比如列表). 除了在使用方面的不同,他们的定义方式是一样的。

搜索视图根元素为<search>。该视图最基础的版本是列出需要快捷方式的所有字段:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<search string="Tests">
    <field name="name"/>
    <field name="last_seen"/>
</search>

Odoo生成的默认搜索视图提供了按name筛选的快捷方式。在自定义搜索视图中添加用户可能过滤的字段是非常常见的。

搜索视图还可以包含<filter>元素,这些元素充当预定义搜索的开关。筛选器必须具有以下属性之一:

  • domain:将给定domain添加到当前搜索
  • dontext:添加一些context到当前搜索,使用group_by按给定字段名称对结果分组。

一个简单的示例.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        <record id="view_delivery_carrier_search" model="ir.ui.view">
            <field name="name">delivery.carrier.search</field>
            <field name="model">delivery.carrier</field>
            <field name="arch" type="xml">
                <search string="Delivery Carrier">
                    <field name="name" string="Carrier" />
                    <field name="delivery_type"/>
                    <separator/>
                    <filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
                    <group expand="1" string="Group By">
                        <filter string="Provider" name="provider" context="{'group_by':'delivery_type', 'residual_visible':True}"/>
                    </group>
                </search>
            </field>
        </record>

在进一步练习之前,有必要介绍一下domain概念。

domain

引用: 本主题相关文档可参考 Search domains.

在odoo中,domain对记录上的条件进行编码:domain是用于选择模型记录子集的条件列表。每个条件都是一个包含字段名运算符的三元组。如果指定字段满足作用于值的运算符的条件,则记录满足条件。

例如,当在Product模型上使用时,以下domain选择单价高于1000的所有services

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[('product_type', '=', 'service'), ('unit_price', '>', 1000)]

默认情况下,条件与隐式AND组合在一起,这意味着记录匹配一个domain,需要满足domain中的每个条件。逻辑运算符&(AND)、|(OR)和!(NOT)可用于显式组合条件。它们用于前缀位置(运算符插入在其参数之前,而不是插入在参数之间)。例如,选择类型为“服务“或“单价”不介于1000和2000之间的产品

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
['|',
    ('product_type', '=', 'service'),
    '!', '&',
        ('unit_price', '>=', 1000),
        ('unit_price', '<', 2000)]

选择类型为“服务“且“单价”介于1000和2000之间的产品

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
['&',('product_type', '=', 'service'),'&',('unit_price', '>=', 1000),('unit_price', '<', 2000)]

等价于

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[('product_type', '=', 'service'),('unit_price', '>=', 1000),('unit_price', '<', 2000)]

选择类型为“服务“或者“单价”大于等于1000或者单价小于500的产品

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
['|', '|', ('product_type', '=', 'service'),('unit_price', '>=', 1000),('unit_price', '<', 500)]

选择名字为 ABC 而且语言编码不为 en_US 而且国家的编码为 be 或者 de

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[('name','=','ABC'),
 ('language.code','!=','en_US'),
 '|',('country_id.code','=','be'),
     ('country_id.code','=','de')]

简单一点的写法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[('name','=','ABC'),
 ('language.code','!=','en_US'),
 ('country_id.code','in', ['be', 'de'])]
波兰表示法简介

Odoo是使用了波兰表示法,简单来说,波兰表示法是一种操作符置于操作数前,并且不需要括号仍然能无歧义地解析表达的方法。

运算顺序 以二元运算为例,从左至右读入表达式,遇到一个操作符后跟随两个操作数时,则计算之,然后将结果作为操作数替换这个操作符和两个操作数;重复此步骤,直至所有操作符处理完毕。

举个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
['|','&','|',a,b,c,'&',d,e]

其中a,b,c,e,f,g 分别是不带逻辑运算符的表达式,表达式的运算顺序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1['|','&','|',a,b,c,'&',d,e]
 
2['|','&',(a | b),c,'&',d,e]
 
3['|',((a | b) & c),'&',d,e]
 
4['|',((a | b) & c),(d & e)]
 
5[(((a | b) | c) | (d & e))]

如果我们要做到这个效果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
A and (B or C) and D and E

先从里面开始,把or提前

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
A and (or B C) and D and E

把里面的and提前,去掉括号

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
and A or B C and D E

所以最后的domain可以这样写

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
A, '|', B, C, D, E

当然,我们也可以把表达式写得更容易看一点,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
A, D, E, '|', B, C
练习

添加定义搜索视图

在合适的XML中为 estate.property 模型定义一个搜索视图

添加过滤和分组

添加以下内容到之前创建就的搜索视图

  • 一个显示avaliable地产的过滤器,也就说,state应该为 “New“ 或者“Offer Received”。
  • 按"postcode"分组的能力

修改odoo14/custom/estate/views/estate_property_views.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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>

    <record id="action_lost_leads" 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>

    <record id="estate_property_view_tree" model="ir.ui.view">
        <field name="name">estate.property.tree</field>
        <field name="model">estate.property</field>
        <field name="arch" type="xml">
            <tree string="Tests">
                <field name="name" string="Title"/>
                <field name="postcode" string="Postcode"/>
                <field name="bedrooms" string="Bedrooms"/>
                <field name="living_area" string="Living Area"/>
                <field name="expected_price" string="Expected Price"/>
                <field name="selling_price" string="Selling Price"/>
                <field name="date_availability" string="Avalilable Form"/>
            </tree>
        </field>
    </record>

    <record id="estate_property_view_form" model="ir.ui.view">
        <field name="name">estate.property.form</field>
        <field name="model">estate.property</field>
        <field name="arch" type="xml">
            <form string="estate property form">
                <sheet>
                    <h1>
                        <field name="name"/>
                    </h1>
                    <group>
                        <group>
                            <field name="postcode" string="Postcode" ></field>
                            <field name="date_availability" string="Available From"></field>
                        </group>
                        <group>
                            <field name="expected_price" string="Expected Price"></field>
                            <field name="selling_price" string="Selling Price"></field>
                        </group>
                    </group>
                    <notebook>
                        <page string="Description">
                            <group>
                                <field name="description"></field>
                                <field name="bedrooms"></field>
                                <field name="living_area"></field>
                                <field name="facades"></field>
                                <field name="garage"></field>
                                <field name="garden"></field>
                                <field name="garden_area"></field>
                                <field name="garden_orientation"></field>
                            </group>
                        </page>
                    </notebook>
                </sheet>
            </form>
        </field>
    </record>

    <!--本小节添加的内容-->
    <record id="estate_property_search_view" model="ir.ui.view">
        <field name="name">estate.property.search</field>
        <field name="model">estate.property</field>
        <field name="arch" type="xml">
            <search string="Estate Property">
                <!-- 搜索 -->
                <field name="name" string="Title" />
                <field name="postcode" string="Postcode"></field>
                <separator/>
                <!-- 筛选 -->
                <filter string="Available" name="state" domain="['|',('state', '=', 'New'),('state', '=', 'Offer Received')]"></filter>
                <filter name="bedrooms" domain="[('bedrooms', '>', 3)]"></filter>
                <filter name="bedrooms and selling_price" domain="[('bedrooms', '>', 2),('selling_price', '>=', 1000)]"></filter>
                <!-- 分组 -->
                <group expand="1" string="Group By">
                    <filter string="朝向" name="garden_orientation" context="{'group_by':'garden_orientation'}"/>
                </group>
            </search>
        </field>
    </record>
</odoo>

重启服务,验证效果

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
odoo 开发入门教程系列-模型之间的关系(Relations Between Models)
上一章介绍了为包含基本字段的模型创建自定义视图。然而,在任何真实的业务场景中,我们都需要不止一个模型。此外,模型之间的链接是必要的。人们可以很容易地想象一个模型包含客户,另一个模型则包含用户列表。你可能需要参考任何现有业务模型上的客户或用户。
授客
2023/04/01
4.8K0
odoo 开发入门教程系列-模型之间的关系(Relations Between Models)
odoo 开发入门教程系列-一些用户界面
上一章,我们通过CSV文件添加了数据。当需要添加数据格式简单时,用CSV格式还是很方便的,当数据格式更复杂时(比如视图架构或者一个邮件模板),我们使用XML格式。比如包含HTML tags的 help field。虽然可以通过CSV文件加载这样的数据,但是使用XML更方便。
授客
2023/03/26
3.3K0
odoo 开发入门教程系列-一些用户界面
odoo 开发入门教程系列-计算的字段和变更(Computed Fields And Onchanges)
模型之间的关系是任何Odoo模块的关键组成部分。它们对于任何业务案例的建模都是必要的。然而,我们可能需要给定模型中字段之间的链接。有时,一个字段的值是根据其他字段的值确定的,有时我们希望帮助用户输入数据。
授客
2023/04/02
3.5K0
odoo 开发入门教程系列-计算的字段和变更(Computed Fields And Onchanges)
odoo 开发入门教程系列-QWeb简史
到目前为止,我们的房地产模块的界面设计相当有限。构建列表视图很简单,因为只需要字段列表。表单视图也是如此:尽管使用了一些标记,如<group>或<page>,但在设计方面几乎没有什么可做的。
授客
2023/04/28
2.4K0
odoo 开发入门教程系列-QWeb简史
odoo 开发入门教程系列-模型和基本字段
在上一章的末尾,我们创建一个odoo模块。然而,此时它仍然是一个空壳,不允许我们存储任何数据。在我们的房地产模块中,我们希望将与房地产相关的信息(名称(name)、描述(description)、价格(price)、居住面积(living area)…)存储在数据库中。odoo框架提供了数据库交互的工具
授客
2023/03/25
2.7K0
odoo 开发入门教程系列-模型和基本字段
odoo 开发入门教程系列-继承(Inheritance)
Odoo的一个强大方面是它的模块化。模块专用于业务需求,但模块也可以相互交互。这对于扩展现有模块的功能非常有用。例如,在我们的房地产场景中,我们希望在常规用户视图中直接显示销售人员的财产列表。
授客
2023/04/23
2.6K0
odoo 开发入门教程系列-继承(Inheritance)
odoo context上下文用法总结
Model.with_context([context][, **overrides]) -> records[源代码]
授客
2023/03/09
2.3K0
odoo 权限管理学习总结
https://apps.odoo.com/apps/modules/12.0/base_user_role/
授客
2023/03/14
10.6K0
odoo 权限管理学习总结
odoo wizard界面显示带复选框列表及勾选数据获取
如下图(非实际项目界面截图,仅用于介绍本文主题),打开记录详情页(form视图),点击某个按钮(图中的"选取ffers"按钮),弹出一个向导(wizard)界面,并将详情页中内联tree视图("Offers" Tab页)的列表记录展示到向导界面,且要支持复选框,用于选取目标记录,然执行目标操作。
授客
2023/05/24
5.7K0
odoo wizard界面显示带复选框列表及勾选数据获取
odoo Actions学习总结
action可以存储在数据库中,也可以作为字典直接返回,例如按钮方法。所有Action都有两个强制属性:
授客
2023/03/09
2.9K0
odoo 给列表视图添加按钮实现数据文件导入
odoo14\custom\estate\models\estate_customer.py
授客
2023/02/26
3.8K0
odoo 给列表视图添加按钮实现数据文件导入
odoo 为form表单视图添加chatter功能
如图,给表单新增一个类似聊天的窗口,当记录一些表单活动(本例为自动记录当前记录状态变化)
授客
2023/02/26
8950
odoo 为form表单视图添加chatter功能
odoo ORM API学习总结兼orm学习教程
默认的,字段的标签(Lable,即用户可见字段名称)为对应字段名称开头字母改成大写后的值,可通过 string 字段属性改成修改字段Label
授客
2023/03/12
14.1K0
odoo ORM API学习总结兼orm学习教程
odoo 给form表单视图内联列表添加按钮
odoo14\custom\estate\models\estate_customer.py
授客
2023/02/26
1.6K0
odoo 给form表单视图内联列表添加按钮
odoo 开发入门教程系列-一个新应用
form视图顶层区域概括了房产的重要信息,比如name,Property Type, Postcode等等。
授客
2023/03/25
1.4K0
odoo 开发入门教程系列-一个新应用
odoo 开发入门教程系列-约束(Constraints)
上一章介绍了向模型中添加一些业务逻辑的能力。我们现在可以将按钮链接到业务代码,但如何防止用户输入错误的数据?例如,在我们的房地产模块中,没有什么可以阻止用户设置负预期价格。
授客
2023/04/08
1.7K0
odoo 开发入门教程系列-约束(Constraints)
odoo 开发入门教程系列-安全-简介
前一章中我们已经创建了第一个打算用于存储业务数据的表。在odoo这样的一个商业应用中,第一个考虑的问题就是谁(Odoo 用户(或者组用户))可以访问数据。odoo为指定用户组用户提供了一个安全的数据访问机制。
授客
2023/03/26
1K0
odoo 为可编辑列表视图字段搜索添加查询过滤条件
如下图,列表网仓记录详情页面(form视图),编辑内联视图中的货主记录,为货主和仓库字段搜索,添加过滤条件,具体如下:
授客
2023/05/24
1.4K0
odoo 为可编辑列表视图字段搜索添加查询过滤条件
odoo 开发入门教程系列-模块交互
在上一章中,我们使用继承来修改模块的行为。在我们的房地产场景中,我们希望更进一步,能够为客户生成发票。Odoo提供了一个开发票模块,因此直接从我们的房地产模块创建发票是很简单的,也就是说,一旦某个房产设置为“已售出”,就会在Invoicing应用程序中创建发票
授客
2023/04/24
2K0
odoo 开发入门教程系列-模块交互
Odoo 自定义form表单按钮点击事件处理程序
通过研究发现,点击odoo form表单按钮时,会调用odoo14\odoo\addons\web\static\src\js\views\form\form_controller.js文件中的_onButtonClicked函数,在该函数中响应点击事件。所以,我们可以通过重写该方法来实现自定义响应点击事件。示例如下
授客
2023/02/26
1.7K0
相关推荐
odoo 开发入门教程系列-模型之间的关系(Relations Between Models)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验