odoo-cookbook

第九章 后端视图

全书完整目录请见:Odoo 14开发者指南(Cookbook)第四版

在此前的章节中,我们学习了Odoo的服务端和数据库层面的知识。本章中将学习Odoo的UI层面的知识。我们将学习如何创建不同类型的视图。除视图外,本章还会讲解组件,如动作按钮、菜单和微件,有助于我们将应用变得对用户更友好。完成本章后,读者将可以设计Odoo后台的UI。注意本章并不包含Odoo的网站部分,会有单独的章节进行讲解。

本章中,我们将讲解如下小节:

技术准备

贯穿本章,我们将假定你的数据库中安装了base插件并且有一个空的插件模块,可以添加各节中的XML代码到插件声明文件所引用的数据文件中。参见第三章 创建Odoo插件模块,获取更多有关应用插件中修改的信息。

本章的技术要求包含一个在线Odoo平台。

本章中所使用的所有代码都在可GitHub仓库中下载:https://github.com/alanhou/odoo14-cookbook

添加菜单项和窗口动作

为用户添加新功能最明显的方式是通过添加菜单项。在点击菜单项时,会发生一些操作。本节将带你学习如何定义这些操作。

我们将创建一个顶级菜单及子菜单,它会打开一个所有客户的列表。

这也可使用网页用户界面借由settings菜单来实现,但更推荐使用XML数据文件,因为在创建我们的插件模块时需要使用此方法。

准备工作

本节中,我们需要一个依赖于account模块的模块,因为account模块对res.partner模型添加了一些将字段用于区分客户和供应商记录。因此,如果使用已有模块,请在声明文件中添加对account的依赖。或者可以直接通过GitHub仓库获取初始模块。

如何实现…

在我们插件模块的XML数据文件中,执行如下步骤:

  1. 定义待执行的动作:

    <act_window id="action_all_customers"
      name="All customers"
      res_model="res.partner"
      view_mode="tree,form"
      domain="[('customer', '=', True)]"
      context="{'default_customer': True}" />
    
  2. 创建顶级菜单,如下:

    <menuitem id="menu_custom_top_level"
      name="My App menu"
      web_icon="my_module,static/description/icon.png"/>
    
  3. 在菜单中引用我们的动作:

    <menuitem id="menu_all_customers"
      parent="menu_custom_top_level"
      action="action_all_customers"
      sequence="10"/>
    

如果我们现在升级模块的话,会看到一个可打开名为All Customers子菜单的顶级菜单My App menu。点击该菜单项会打开一个所有客户的列表。

运行原理…

第一个XML元素act_window,定义了一个展示带有所有客户列表视图的窗口动作。我们使用了最重要的属性:

📝小贴士:在老代码中,你会经常看到tree视图模式。这是截至并包含Odoo 11中所使用的内部名称。版本12还接收该值,但会等同于list来进行处理。

接下来,我们创建顶级菜单到可点击的末梢菜单项的菜单项等级。menuitem元素最重要的属性如下:

窗口动作自动决定以所希望的类型(form, tree等等)对目标模型查找所使用的视图,并选择序号最低的那个。

act_window和menuitem是隐藏所进行操作的快捷XML标签。如果不想使用快捷XML标签,那么可以通过该标签创建一个ir.actions.act_window和ir.ui.menu模型的记录。例如,如果想要通过加载act_window,可以这么做:

<record id='action_all_customers' model='ir.actions.act_window'>
  <field name="name">All customers</field>
  <field name="res_model">res.partner</field>
  <field name="view_mode">tree,form</field>
  <field name="domain">[('customer', '=', True)]</field>
  <field name="context">{'default_customer': True}</field>
  <field name="limit">20</field>
</record>

你可以相同的方式通过创建menuitem。

📝重要信息:注意menuitem快捷标签中使用的名称可能不会映射到使用record元素(parent应为parent_id,groups应为groups_id)时所用的字段名。

要创建菜单,网页客户端从ir.ui.menu读取所有的记录并从parent_id字段推导它们的等级。菜单还会根据赋给菜单和动作的模型和组的用户权限来进行过滤。在用户点击菜单项时,执行它的动作。

扩展知识…

窗口动作还支持target属性,用于指定如何展现视图。可选项如下:

窗口动作的view_type属性现在大多已经淘汰。默认的表单的替代为tree,会引起分组列表渲染一个等级树。不要将这个属性与本节运行原理中使用和讲解的view_mode属性相混淆,那是决定所使用的视图类型的。

对于窗口动作有一些额外的可用属性,在act_window快捷标签中不支持。要使用这些属性,我们需要使用带有如下字段的record元素:

记住左上角的菜单(或是企业版中应用的图标)及顶栏中的菜单都是由菜单项所组成。唯一的不同的是左上角中菜单没有父级菜单,但顶栏上的这些菜单有顶栏的相应菜单项作为父级。在左栏中,等级结构更为明显。

同时应记住出于设计原因,如果第二级菜单有子菜单时第一级菜单会打开下拉菜单。Odoo会根据子菜单项的排序打开第一个菜单项动作。

参照如下内容来学习有关菜单和视图的更多知识:

其它内容

打开指定视图的动作

在未指定时窗口动作自动决定所使用的视图,但有时,我们希望一个动作打开具体某一视图。

我们会为res.partner模型创建一个基本表单视图,并且随后新建一个具体打开该表单视图的窗口动作。

如何实现…

  1. 定义partner的最小化树状和表单视图:

    <record id="view_all_customers_tree" model="ir.ui.view">
      <field name="name">All customers</field>
      <field name="model">res.partner</field>
      <field name="arch" type="xml">
        <tree>
          <field name="name" />
        </tree>
      </field>
     </record>
     <record id="view_all_customers_form" model="ir.ui.view">
      <field name="name">All customers</field>
      <field name="model">res.partner</field>
      <field name="arch" type="xml">
        <form>
          <group>
            <field name="name" />
          </group>
        </form>
      </field>
     </record>
    
  2. 更新

    添加菜单项和窗口动作

    一节中的动作来使用新的表单视图:

    <record id="action_all_customers_tree"
      model="ir.actions.act_window.view">
      <field name="act_window_id" ref="action_all_customers" />
      <field name="view_id" ref="view_all_customers_tree" />
      <field name="view_mode">tree</field>
      <field name="sequence" eval="2"/>
    </record>
    <record id="action_all_customers_form"
      model="ir.actions.act_window.view">
      <field name="act_window_id" ref="action_all_customers" />
      <field name="view_id" ref="view_all_customers_form" />
      <field name="view_mode">form</field>
      <field name="sequence" eval="2"/>
    </record>
    

现在如果打开菜单并点击列表中的成员,你会看到刚刚定义的最小化表单和列表。

运行原理…

这次,我们使用了针对任意记录类型通用XML代码,即带有所需 id 和model属性的record元素。record元素上的id属性是任意一个在插件中唯一的字符串。model属性引用所希望创建的模型。假定我们想要创建视图,则需要创建一个 ir.ui.view模型的记录。在该元素内, 我们设置通过model属性选取模型中定义的字段。对ir.ui.view最关键的字段是model和arch。model字段包含所想要定义视图的模型而arch字段包含视图本身的定义。稍后我们就会讲到它的内容。

name字段虽然不是严格必要,但有助于通过视图调试问题,因此将其设置为一个字符串可以告诉我们这个视图的作用。该字段的内容不对用户显示,因此可以填入任意对你有意义的技术性提示。如果不进行设置,会得到一个包含模型名和视图类型的默认名称。

ir.actions.act_window.view

我们所定义的第二条记录与在前面添加菜单项和窗口动作小节中定义的act_window一同发挥作用。我们已经知道通过设置view_id字段,可以选择第一个视图模式所使用的视图。但是,假设我们将view_mode设置为tree, form视图,view_id则应选择树状视图,但我们想要设置的是表单视图,放在第二位。

如果你发现自己遇到同样的状况,使用ir.actions.act_window.view模型,它会对哪种视图类型加载何种视图进行更细致的控制。这里定义的前两个字段是引用其它对象的通用方式示例,保持元素体为空,但添加一个ref属性,它包含所想要引用的对象的XML ID。因此这里所发生的是我们在act_window_id字段中引用前一小节中的动作,并引用我们刚刚在view_id中所创建的视图。然后,虽非严格必要,我们添加了对同一动作这一视图赋值相对于其它视图赋值的序号。仅在通过创建多条ir.actions.act_window.view记录为不同视图模式添加视图时才有关联。

📝重要信息:一旦定义了 ir.actions.act_window.view记录,其优先级高于在动作的view_mode字段中所填写内容。因此在前面的记录中,看不到列表视图,仅有表单视图。需要添加另一个指向针对res.partner模型列表视图的ir.actions.act_window.view。

扩展知识…

我们在添加菜单项和窗口动作一节中学习了可以将act_window替换为。如果想要使用自定义视图,可以遵循给定的语法:

<record id='action_all_customers'
  model='ir.actions.act_window'>
  <field name="name">All customers</field>
  <field name="res_model">res.partner</field>
  <field name="view_mode">tree,form</field>
  <field name="domain">[('customer', '=', True)]</field>
  <field name="context">{'default_customer': True,
    'tree_view_ref': 'my_module.view_all_customers_tree'.
    'form_view_ref': 'my_module.view_all_customers_form'
  }</field>
  <field name="limit">20</field>
</record>

上例只是act_window的另一种书写方式,在Odoo的基础代码中,会发现存在这两种类型的动作。

向表单视图添加内容和微件

前面一节展示了如何为一个动作选择指定的视图。现在我们将演示如何让表单视图更为实用。本节中,我们将使用在指定视图中打开动作一节中所定义的表单视图。在表单中视图中添加微件和内容。

如何实现…

  1. 定义表单视图的基础结构:

    <record id="view_all_customers_form" model="ir.ui.view">
      <field name="name">All customers</field>
      <field name="model">res.partner</field>
      <field name="arch" type="xml">
        <form>
          <!--form content goes here -->
        </form>
      </field>
    </record>
    
  2. 头部栏通常用于放置动作按钮和进度管道,在表单中使用如下代码添加一个头部栏:

    <header>
      <button type="object" name="open_commercial_entity"
        string="Open commercial partner"
        class="btn-primary" />
    </header>
    
  3. 在表单中添加字段,使用group标签进行视觉上的组织:

    <group string="Content" name="my_content">
      <field name="name" />
      <field name="category_id" widget="many2many_tags" />
    </group>
    

现在表单中应该会显示带有一个按钮的顶栏以及两个垂直对齐的字段,如下图所示:

图9.1 – 表单视图截图

图9.1 – 表单视图截图

运行原理…

我们先来看ir.ui.view模型中的arch字段。首先,注意视图使用用XML进行定义,因此需要向arch字段传递type=”xml”属性,否则会让解析器不知所措。同时还要求视图定义中必须包含良好的XML结构,否则在加载这个代码段时会出现问题。

下面我们来逐一学习前面所使用的标签并对其它的可用标签进行总结。

form

在定义表单视图时,arch字段的第一个元素必须为form元素。内部通过它来获取记录的type字段,

除下面的元素以外,还可以在form标签内使用自定义的HTML。对Odoo未知的元素算法均会视为普通的HTML并直接传递给浏览器。要谨慎使用,因为所填充的HTML会与Odoo元素生成的HTML代码进行交互,可能会让渲染出现偏差。

这个元素是显示在表单头部中元素的容器,它被渲染为一个白条。通常会像示例中一样将动作按钮放在这里。此外,如果模型有state字段的话,也可以选择状态栏。

button

button元素用于允许用户触发某一动作。参见向表单添加按钮一节获取更多信息。

group

元素是Odoo的主要元素,用于组织内容。元素中的字段以它们的标题进行渲染,并且相同组中的所有字段进行了对齐,这样在视觉上可以看出它们属于相同组。还可以内嵌元素,这会让Odoo将所包含字段以相邻的列进行渲染。 通常,应使用组织方式来在表单视图中显示所有字段,仅在必要时才考虑其它元素,如,
``` 4. 添加主要字段: ```
``` 5. 添加内容,如果有很字段的话可以使用notebook: ``` ``` 6. 在sheet之后,添加chatter微件(如若可用): ```
``` 如们来了解本节代码是如何运行的。 ![定义文档样式表单](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021043009181963.png) ### 运行原理... 头部包含对当前用户可见的对象执行动作的按钮。使用btn-primary类来让按钮在视觉上更突出(在写本书时颜色为紫色),这对于引导用户在当前执行最符合逻辑的动作会是一种很好的方式。试着将所有高亮的按钮放在非高亮按钮的左侧并隐藏与当前状态(若有)中无关的按钮。如果该模型有状态,在头部中使用statusbar微件来进行显示。它会在头部居右显示。 sheet元素以样式化单据的形式渲染,并且最重要的字段应放在用户第一眼看到的地方。使用oe_title和oe_left类来让它们在显著的位置进行显示(在写本书时样式为以微调的字体大小居左显示)。 如果有涉及用户当前所见记录的其它有意义的字段(比如partner表单上的用户发票),把它们放在一个带有oe_right和oe_button_box类的元素中,这会将按钮向右对齐。按钮自身可使用oe_stat_button类来强制按钮的统一样式渲染。也可以通过对icon属性设置Font Awesome图标来自定义指定图标类。有关Font Awesome的更多内容参见https://fontawesome.com/v4.7.0/icons/。 我们可以使用oe_chatter类和Chattert微件来在表单视图的底部获取默认的留言区。这时需要使用mail.thread mixin。我们将在[第二十三章 在Odoo中管理Email](https://alanhou.org/odoo-14-manage-emails-odoo/)中进行详细学习。 > 📝**重要提示**:即便你不喜欢这种布局,也请使用上述的元素和类名,然后使用CSS和JavaScript来进行所要做的调整。这会让你的用户界面与已有的插件相兼容并会与核心插件集成地更好。 ### 其它内容 - 访问https://fontawesome.com/v4.7.0/icons/进一步了解Font Awesome - 参见[第二十三章 在Odoo中管理Email](https://alanhou.org/odoo-14-manage-emails-odoo/)学习有关**mail.thread** mixin更进一步的知识 ## 使用attrs的动态表单元素 至此,我们只学习了根据用户组来修改表单(元素上的groups属性和继承视图中的groups_id字段)。本节我们将展示如何根据其它字段的值来修改表单视图。 ### 如何实现... 1. 在表单元素上定义一个名为attrs的属性: ``` ``` 2. 确保你所引用的所有字段都在表单中可用: ``` ``` 如果用户是公司的话会让parent_id字段不可见,而在非公司时又为必填字段。 ![使用attrs的动态表单元素](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021043009303577.png) ### 运行原理... attrs属性包含有invisible、required和readonly键的字段(这些都是可选的)。值为所引用表单中存在字段(也仅有这些,因此没有点号路径)的作用域,整个字典根据客户端Python规则运行,在本章中*向表单视图添加内容和微件*一节已有表述。比如你可以在右侧运算项中访问上下文。 ### 扩展知识.... 虽然这一机制对于标量字段非常明了,对于如何处理one2many和many2many字段则不太清晰。事实上在标准的Odoo中,对于这些字段我们在attrs属性中做不了什么。但如果你需要查看字段是否为空的话,可以在右侧运算项中使用[[6, False, []]]。 ## 定义内嵌视图 在表单中显示one2many或many2many字段时,如未使用特殊微件则对其如何渲染不太可控。同时对于many2one字段,有时要求能够影响所关联记录的打开方式。本节中,我们将学习如何为这些字段定义私有视图。 ### 如何实现... 1. 像平常一样定义字段,但不关闭标签: ``` ``` 2. 在标签中编写视图定义: ```
``` 3. 关闭标签: ```
``` ![定义内嵌视图](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021043009545313.png) ### 运行原理... 在Odoo加载表单视图时,首先会查看关联类型字段中是否有嵌套视图,前面已有指出。这些嵌套视图可以像我们前面所定义视图有完全相同的元素。仅在Odoo没有找到某些类型的嵌套视图时,它才使用这种类型的默认模型视图。 ### 扩展知识.... 虽然嵌套视图看上去是一个很棒的功能,但它让继承视图变得过于复杂。例如,在涉及到嵌套视图时,字段名不能保证唯一性,通常会需要使用一些更复杂的XPath来在嵌套视图中选择元素。 因此,通常应该更好地定义独立视图并使用form_view_ref和tree_view_ref键,这在本章*在指定视图中打开动作*一节中进行了讲解。 ## 在表单视图边栏显示附件(企业版) 在一些应用中,比如发票,需要根据文档填写数据。为让数据填写过程更为轻松,在Odoo 12中添加了一种新功能来在表单视图的边栏显示文档。 本节中,我们将学习如何背靠背地显示表单视图和文档: ![图9.3 – 层叠附件和表单视图](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021043010231738.jpg) 图9.3 – 层叠附件和表单视图 > 📝**重要信息**:这一功能仅用于大显示器(>1534px),所以在你的视窗较小时,这一功能会隐藏。在内部该功能使用了一些响应式工具,因此该功能仅用于企业版。但你还是可以在模块中使用这段代码。Odoo会自动进行处理,因此如果在企业版中安装这个模块,会显示该文档,而在社区版中,它会进行隐藏且不会产生任何问题。 ### 如何实现... 我们将启用这一功能来为res.partner 模型修改表单视图,代码如下: ``` All customers res.partner
``` 更新模块以应用修改。需要通过记录聊天区上传一个PDF或图片。上传时,Odoo会在侧边显示该附件。 ### 运行原理... 这一功能仅在模型继承了mail.thread模型时才起作用。在表单视图边栏显示文件档,需要在chatter元素前添加一个带有o_attachment_preview类的空
。这样就好了,附加在chatter中的文档就会在表单视图的边栏显示。 默认,pdf和图片文档会按照日期升序显示。可通过添加选项来改变这一行为,选项如下: - type:需要传递一个希望允许的文档类型列表。仅能使用两个值:pdf和image,例如,如果仅希望显示pdf类型的文件,可传递{'type': ['pdf']}。 - order:可用的值有asc和desc。让我们可以使用文档创建日期升序或降序来显示文档。 ### 扩展知识.... 大多数情况下,你会希望在记录初始状态的边栏显示文档。如果想要根据域来隐藏附件预览,可以对
标签使用attrs来隐藏预览。 看如下示例,它会在state字段不为draft时隐藏PDF预览: ``` <div class="o_attachment_preview" attrs="{'invisible': [('state', '!=', 'draft')]/> ``` 这就是在不需要时隐藏附件的方式。通常这个功能用于通过PDF填充数据,仅在草稿模式进行激活。 ## 定义看板视图 到此,我们向大家展示了一系列可以打开显示表单的记录。虽然这些列表对于展示大量信息非常有效,但因缺乏设计感而稍显无趣。本节中,我们会来学习看板视图,可让我们以更美观的方式展示记录列表。 ### 如何实现... 1. 定义kanban类型的视图: ``` All Customers res.partner ``` 2. 列出在视图中使用的字段: ``` ``` 3. 实现设计: ```
is a customer and a supplier
``` 4. 关闭所有标签: ```
``` 5. 将该视图添加到动作当中。这部分将留给读者作为练习。可以在GitHub的示例文件中找到完整示例:https://github.com/alanhou/odoo14-cookbook/tree/main/Chapter09/15_kanban_view ![定义看板视图](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021050101133464.png) ### 运行原理... 在第2步中我们需要给出一个字段列表来在稍后访问。templates元素的内容必须是t-name属性设置为kanban-box的单个t元素。 该元素中所编写内容会在每条记录中重复,带有针对 t 元素的特殊语法及t-*属性。有关它的细节,参见[第十五章 网页客户端开发](https://alanhou.org/odoo-14-web-client-development/)中*使用客户端QWeb模板*一节,因为在技术上看板视图不过是QWeb模板的一个应用。 有一些特别针对看板视图的修改。可以在运行时使用变量read_only_mode、record和widget。字段可通过record.*fieldname*来进行访问,它是一个带有value和raw_value属性的对象,value是格式化为用户可以看得懂的字段值,raw_value是直接从数据库中取的值。. > 📝**重要信息**:Many2many字段是一个例外。通过变量record只能获取到ID列表。要显示为用户可读的内容,应使用field元素。 注意在模板顶部的链接中的type 属性。该属性让 Odoo 以浏览模式(open)或编辑模式(edit)生成一个打开记录的链接,或者会删除该记录(delete)。type属性也可以是对象或动作,会渲染调用模型的函数或动作的链接。两种情况下,都需要为表单视图中的按钮补充属性,如本章*向表单添加按钮*一节中所述。除 a 元素外,还可以使用button元素,这里type属性的语法相同。 ### 扩展知识.... 有一些值得一提的帮助函数。如需为元素生成一个伪随机颜色,使用kanban_color(*some_variable*) 函数,它将返回一个设置background和color属性的CSS类。这通常用于t-att-class元素。 如果想要显示一个存储在二进制字段存储的图像,使用kanban_image(*modelname*, *fieldname*, record.id.raw_value),如果在字段列表中包含了该字段并该字段已设置它返回一个数据URI,若字段未设置返回占位符,或如未在字段列表中包含该字段则返回一个由Odoo提供字段内容流的 URL。如果需要同步显示大量记录或图像很大时请不要在字段列表中包含该字段。通常在img元素的t-att-src属性中使用它。 > **📝重要贴士:**在看板视图中进行设计很磨人。通常更好的做法是使用HTML类型的函数字段生成HTML,并通过Qweb视图生成这一HTML。这种方式使用的是QWeb,但在服务端,在需要操作大量数据时会方便很多。 ### 其它内容 - 要学习有关模板元素的知识,参见[第十五章 网页客户端开发](https://alanhou.org/odoo-14-web-client-development/)中*使用客户端QWeb模板*一节。 ## 根据状态在列中显示看板卡片 本节向读者展示如何设置看板视图,在其中可将记录从一列拖拽到另一列,因而将所操作的记录移到另一种状态。 ### 准备工作 从这里开始,我们将使用project模块,因为它定义的模型比那些base模块中定义的模型更适用于基于日期和基于状态的视图。所以在开始学习之前先将project添加到插件的依赖列表中。 ### 如何实现... 1. 为任务定义一个看板视图: ``` project.task.kanban project.task
``` 2. 使用该视图添加菜单和动作。这部分留作读者练习。 ![根据状态在列中显示看板卡片](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021050101390178.png) ### 运行原理... 看板视图支持分组,让我们可以在同一列中显示有相同分组字段的记录。这通常用于state或stage_id字段,因为它让用户可以将其简单拖拽到另一个列中修改该字段的值。对kanban元素设置default_group_by属性成为想要分字段名来使用这一功能。 要控制看板分组的行为,在Odoo中有一些可用的选项: - group_create:该选项用于在分组的看板中隐藏或显示Add a new column选项。默认值为true。 - group_delete:该选项在看板组上下文菜单中启用或禁用Column delete选项。默认值为true。 - group_edit:该选项在看板组上下文菜单中启用或禁用Column edit选项。默认值为true。 - archivable:该选项在看板组上下文菜单中启用或禁用存档和恢复记录的选项。仅用于存在active布尔字段的模型。 - quick_create:通过这一选项,可以直接从看板视图中创建记录。 - quick_create_view:quick_create默认仅在看板中显示name字段。但通过quick_create_view选项,可以给出最小化表单视图的引用 来在看板中显示。 - on_create:如果想要在新建记录时使用quick_create并且不希望将用户重定向到表单视图,可以给出向导的引用来在点击Create按钮时打开向导。 ### 扩展知识.... 如未在单独属性中定义,搜索过滤器可通过对字段名设置名为group_by的上下文键来进行分组。 ## 定义日历视图 本节将带你学习如何以可视化的方式在显示和编辑记录中日期和时长的信息。 ### 如何实现... 按照如下步骤来为project.task模型添加一个日历视图: 1. 定义一个calendar视图: ``` project.task ``` 2. 使用该视图添加菜单和动作。这部分留作读者练习。 ### 运行原理... 日历视图需要在date_start和date_stop属性中传递字段名来表明构建可视化展示时查找哪些字段。仅使用Datetime或Date类型的字段,其它类型的字段会无法运行并产生报错。date_start是必填项,但可留空date_stop及使用date_delay属性来进行取代,它应为按小时表示时长的浮点字段。 日历视图让我们可以给带有相同值的字段同样的颜色(可自行指定)。使用这一功能,将color属性设置为所需的字段名。本例中,我们可以快速地看出哪些任务属于相同的项目,因为我们将project_id设置成了决定颜色分组的字段。 在calendar元素体中所命名的这些字段在代表由逗号分隔的时间间隔区间中显示。 ### 扩展知识.... 日历视图有一些有用的属性。如果想要在弹窗而非标准表单视图中打开日历条目,请将event_open_popup设置为1。默认只需填写文本来创建新条目,在内部调用模型的name_create函数来实际创建记录。若想要禁用这一行为,将quick_add设置为0即可。 如果模型范围是一整天,对涵盖一整天记录将all_day设置为是true的字段名,否则设置为false的字段。 ![定义日历视图](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021050103561277.png) ## 定义图表和透视表视图 本节中,我们将学习Odoo的 BI(商业智能)视图。它们是用于展示数据的只读视图。 ### 准备工作 这里我们仍将使用project模块。可以配置graph和pivot视图来获取不同的统计数据。本例中我们仅查看已分配任务的用户。我们将生成图表和透视表视图来查看每个用户的任务。同时,终端用户可以通过修改视图选项来生成他们所选的统计数据。 ### 如何实现... 1. 使用柱状图定义图表视图: ``` project.task ``` 2. 定义透视表视图: ``` project.task ``` 3. 使用该视图添加菜单和动作。这部分留作读者自行练习。 如果一切顺利,应该可以看到显示分配给哪个用户多少任务的图表以及这些任务的状态。 ![定义图表视图](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021050104115142.png) ![定义透视表视图](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021050104121541.png) ### 运行原理... 图表视图通过graph根元素声明。graph元素中的type属性决定了图表视图的初始模式。可用的值有bar, line和chart,默认值是bar。图表视图交互性很强,因此用户可以在不同模式间切换并且还可以添加和删除字段。如要使用 type="bar",还可以使用stacked="1"来在分组时显示叠放的柱状图。 field元素告诉Odoo在哪个轴上显示什么。对于所有的图表模式,至少需要一个带有row类型的字段以及一个带有measure类型的字段来显示有用的信息。row类型的字段决定分组,而那些measure类型的字段表示要显示的值。折线图每种类型仅支持一个字段,而图表和柱状图可很好地处理同一度量方式的两个分组字段。 透视表视图有其自己的根元素pivot。透视表视图支持定义的任意数量的group和measure字段。切换到不支持所定义的group和measure数量的模式并不会导致崩溃,只是有些字段会被忽略,呈现的结果会不够丰满。 ### 扩展知识.... 对于所有图表类型,Datetime字段都不太好分组,因为很少会碰到相同的字段值。因此,如果有row类型的Datetime字段时,同时指定带有如下值的interval属性:day, week, month, quarter或year。这会以给定的间隔进行分组。 透视表还支持对列的分组。对相应的字段使用col类型。 > 📝重要信息:类似于排序,分组也重度依赖于PostgreSQL。因此这里应用规则的字段必须在数据库的当前表中存在方能使用。 > > 定义搜集所需所有数据的数据库视图,并对该视图定义模型来让所有需要的字段可用是常见的做法。 > > 根据视图和分组的复杂度,构建图表可能会是一个开销很大的操作。这时考虑将auto_search设置为False,这样用户可以先调整所有参数,然后才触发一次搜索。 透视表视图还支持按列分组。对希望进行分组的字段使用col类型。 ## 定义流存(cohort)视图(企业版) 对于记录的存留分析,在 Odoo 12中新增了cohort视图。流存视图用于发现指定时间段中记录的生命周期。通过流存视图可以看到指定时间任意对象的流失率和存留率。 ### 准备工作 流存视图是Odoo企业版中的功能,因此在社区版中无法使用。如果你使用的是企业版,需要在模块的声明文件中添加web_cohort。本例中我们将创建视图来查看任务的流存分析。 ### 如何实现... 按照如下步骤来为project.task模型添加cohort视图: 1. 定义一个cohort视图: ``` project task cohort project.task ``` 2. 使用该视图添加菜单和动作。这部分留作读者自行练习。 ![定义流存(cohort)视图](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021050104394469.png) ### 运行原理... 要创建流存视图,需要传递date_start和date_stop。它们在视图中用于决定任意记录的时间区间。例如,如果管理服务的订阅,订阅的开始时间为date_start,订阅过期的日期则为date_stop。 默认,流存视图会以月为间隔在存留模式中显示。可以使用给定的选项来实现流存视图中不同的行为: - mode:可以使用两种模式:retention(默认值:存留)或churn(流失)。retention模式初始为100%,随时间减少,而churn模式初始为0%,随时间增加。 - timeline:该选项接收两个值:forward (默认值)或backward。大部分情况下,需要使用前向时间轴。但如果date_start是未来的时间,会需要使用回退的时间轴。使用逆向时间轴的一个示例是活动参与人员的注册,这时活动日期在未来而注册日期为过去。 - interval:默认流存按月分组,但可以在interval选项中进行修改。月之外,cohort还支持按日、按周和按年的时间间隔。 - measure:类似图表和透视表,measure用于显示给定字段的总计值。如果没有给定任何选项,cohort会显示记录的条数。 ## 定义仪表盘视图(企业版) Odoo 12中引入了一种新的视图,名为仪表盘。它用于在同屏中显示多个视图以及不同的业务KPI。 ### 准备工作 仪表盘视图是Odoo企业版中的功能,因此在社区版中无法使用。如果使用的是企业版,需要在模块的声明文件中添加对web_dashboard依赖。 本例中,我们将展示一些KPI和已有视图。我们会在同屏中显示图表和透视表视图,因此如果还没有创建透视表和图表视图的话,请参照*定义图表和透视表视图*一节进行创建。我们将在仪表盘视图中使用这些视图的ID。我们会在仪表盘视图中使用这些视图的 ID。 ### 如何实现... 1. 定义一个dashboard视图: ``` project task dashboard project.task ``` 2. 使用该视图添加菜单和动作。这部分留作读者自行练习。 ### 运行原理... 通过仪表盘视图,可以用汇总和方程显示KPI。可以在同屏中展示多个视图。如果看视图的定义,会看到我们添加的两个视图:一开始的图表视图和最后的透视表视图。显示这些视图,仅需使用带有 XML 引用和视图类型的标签。 我们通过标签展示了不同的KPI,包括所有任务,进行中任务和已完成任务。该标签将展示搜索视图当前域中记录的总计结果。在标签中,可以使用可选的domain属性来显示指定记录集合的总计。默认aggregate函数显示记录的条数,但可通过使用group_operator属性来指定一个SQL总计函数,如avg或max。 有时无法使用展示KPI,需要一些其它的计算。借助于,我们可以为任意KPI定义公式。本例中,我们展示了所有任务的进度并使用了可选属性widget来将该值展示为百分比。 ### 扩展知识.... 另一个有用的元素是标签。通过它可以在所选的用户界面中显示数据。在[第十五章 网页客户端开发](https://alanhou.org/odoo-14-web-client-development/)中,我们将学习如何创建自定义微件。 ## 定义甘特视图(企业版) Odoo 13中新增了带有新选择的甘特视图。甘特视图对于查看整理进度及规划业务流程非常有用。本节中我们新建一个视图并学习其选项。 ### 准备工作 甘特视图属于企业版,所以在社区版中无法使用。如果使用的是企业版,需要在模块的声明文件中添加对web_gantt的依赖。 本例中,我们将继续使用前面小节中的my_project模块。我们将对项目任务新建一个甘特视图。 **译者注**:如果要在社区版中使用,可以使用OCA的web仓库中具有相似功能的模块web_timeline。该模块引入了一种视图,类似于甘特图的展示。 ### 如何实现... 1. 对任务模型定义甘特视图如下: ``` project task gantt project.task ``` 2. 使用该视图添加菜单和动作。这部分留作读者练习。 安装升级模块应用修改,在更新后,就可以看到项目任务的甘特视图了。 ### 运行原理... 通过甘特视图,可以显示在同屏中显示整体规划。本例中,我们按项目分组对任务创建了甘特视图。正常我们需要两个属性来创建甘特视图:date_start和date_stop,还有一些可扩展甘特视图功能的功能。我们来看下这些选项: - date_start:定义甘特项的开始日期。必须为date或datetime字段。 - date_stop:定义甘特项的结束日期。必须为date或datetime字段。 - default_group_by:如要想根据字段对gantt项进行分组使用些属性。 - color: 这个属性用于决定甘特项的颜色。 - progress: 这个属性用于表明甘特项的进度。 - decoration-* : 装饰属性用于根据条件显示甘特项的颜色。使用方式类似:decoration-danger="state == 'lost'"。其它的值有decoration-success, decoration-info, decoration-warning和decoration-secondary。 - scales: 如果只想使用甘特视图的某几个刻度可以使用scales属性。 例如,如果只想显示天和周的刻度,可以使用scales="day,week"。 - 默认甘特视图项可以重置大小、可拖拽,但如果希望禁用该功能,可以使用edit="0"属性。 ### 扩展知识.... 悬浮甘特视图某项时,会出现该项的名称和日期。如果想要自定义弹出内容,可以在甘特视图中像下面这样定义一个QWeb 模板: ``` project task gantt project.task
  • Name:
  • Stage:
``` 注意需要通过标签在模板中增加希望添加的字段。 ![定义甘特视图](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021050106590391.png) 译者注:为便于演示效果,上例使用了date_stop="date_deadline"和color="stage_id" ## 定义活动视图 活动是Odoo应用的重要组成部分。用于对不同的业务对象调度待办动作。activity视图有助于我们查看状态并规划模板中所有活动。 ### 准备工作 本例中,我们继续使用前面小节中的my_project模块。我们将对项目的任务新建活动视图。 ### 如何实现... 1. 对任务模型定义活动视图如下: ``` project task activity project.task
``` 2. 使用该视图添加菜单和动作。这部分留作读者练习。 ![定义活动视图](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021050107174140.png) ### 运行原理... 活动视图走极简风,大部分内容都自动管理。只有用于自定义第一栏的选项。要在第一列中显示数据,需要创建带有activity-box名称的QWeb模板,就是这么简单。Odoo会处理其余的工作。 活动视图会在第一列显示模板,其它列按活动类型显示计划的活动。 ## 定义地图视图(企业版) Odoo 13新增了一个名为map的视图。从名字可知,用于显示带有标注的地图。这对于线下服务非常有用。 ### 准备工作 本例中,我们将继续使用前面小节中的my_project模块。我们会对任务的客户新建地图视图。地图视图属于Odoo企业版,所以在社区版中无法使用。如果使用的是企业版,需要在模块的声明文件中添加web_map依赖。 Odoo使用https://www.mapbox.com/的API来在视图中显示地图。要在Odoo中查看地图,我们需要通过mapbox生成访问令牌。确保已生成访问令牌并在Odoo的配置中进行了设置。 ![Access Token 配置](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021050115472020.png) ### 如何实现... 1. 对任务模型定义地图视图如下: ``` project task map project.task ``` 2. 使用该视图添加菜单和动作。这部分留作读者练习。 **译者注:**Odoo 中已移除标签,原文表述不太准确。参见https://github.com/odoo/odoo/pull/34655。 ![定义地图视图](https://i.cdnl.ink/homepage/wp-content/uploads/2021/01/2021050115480538.png) ### 运行原理... 创建地图视图非常简单:只需一个引用res.partner模型的many2one字段。res.partner模型有一个address字段,由地图视图用于显示该地址的标注。我们需要使用res_partner属性在地图视图中对应出地址。本例中,我们使用了partner_id字段,因为在partner_id字段中设置了客户记录。 此外,可以自定义用户点击标注时在标注弹窗中显示的字段。~~要显示标注弹窗中的数据,需要使用标签并在其中放置显示字段。~~