其他分享
首页 > 其他分享> > doo 13 之11 :开发之看板视图和用户端 QWeb

doo 13 之11 :开发之看板视图和用户端 QWeb

作者:互联网

QWeb 是 Odoo 使用的模板引擎,它基于 XML 来生成 HTML 片断和页面。通过 QWeb可生成内容丰富的看板(Kankan)视图、报表和 CMS 网页。本文中我们将学习QWeb 语法以及如何使用 QWeb 来创建我们自己的看板视图和自定义报表。

本文主要内容有:

开发准备

我们将继续使用第十章 Odoo 13开发之后台视图 – 设计用户界面完成的library_checkout插件模块。相应代码请见 GitHub仓库。本章完成后的代码也请参见GitHub仓库。

了解看板

Kanban 是一个日语词汇,字面意思榜单,与精益制造和准时化生产相关联,由丰田工业工程师大野耐一(Taiichi Ohno)引入。最近看板的概念应用于更多领域,并且随着敏捷方法的施行在软件工业内流行起来。

看板让我们能够可视化工作队列,它以列来进行组织,每列代表工作进程的一个阶段。工作项以放在看板对应列的卡片来表示。新的工作项从最左边的列开始,并开始向右移动直至最右边列,代表工作完成。

看板的简单化或视觉效果让其对简单的业务流程有着优异的支持。一个基本的看板示例包含三列,如下图所示:待办、在办和完成。当然它可以扩展为你需要的其它指定流程:

对许多业务用例,看板都是管理相应流程的更有效方式,与 Odoo 11之前的更重的工作流引擎形成鲜明对比。Odoo 在支持经典的列表和表单视图的同时还支持看板视图,这易于我们实施这种类型的视图。下面就让我们一起来学习如何使用看板视图。

看板视图

现在我们要为借阅模型添加一个看板视图。每个借阅是一个卡片,看板将会被组织成阶段列。在前面的文章中,我们已经添加了stage_id阶段字段。

此前在表单视图我们大部分时候使用 Odoo 独有的 XML 元素,比如<field><group>,有时也会使用 HTML 元素,如<h1><div>,但用得较少。在看板视图中则恰恰相反,展示模板基于 HTML,仅支持两个 Odoo 独有的元素:<field><button>

最终呈现在网页客户端中的内容是由 QWeb 模板动态生成的。QWeb 引擎处理特殊的 XML 标签和属性来进行生成。这样可以很好地控制如何渲染内容,但也让视图设计更为复杂。看板视图设计灵活性很强,我们将尽力以直接易懂地方式介绍快速创建看板视图的知识。查看与所需相似的看板视图来获取创意然后创建自己的看板是一种不错的方法。

我们将学习两种使用看板视图的方式。一种是卡片列表,它用于联系人、产品、雇员通讯录或应用等。

但这不是真正的看板,看板应是一个组织成不同列的卡片,当然看板视图也支持这种布局。可能过 CRM 或项目应用来查看示例。访问CRM > Sales > My Pipeline可得到结果。

这两种布局的最大区别是卡片按列的组织方式。这通过 Group By 功能实现,与列表视图中相似。通常分组是通过stage字段实现。看板视图的一个非常有用的功能是可以在列之间拖放卡片,自动分配分组视图字段的对应值。从两个示例中的卡片我们可以看到一些分别。其实它们的设计非常灵活,设计看板卡片不只有一种方式。这两个示例为我们提供设计的一些基础。

联系人卡片基本组成有左侧的图像,主区域的加粗标题和紧随其后的一系列值。CRM 管道卡片结构更为复杂些。卡片主区域也有一个标题以及相关信息紧随其后,还有 footer 区。在该区域中,可看到左侧有一个优先级组件,后面带有一个活动指示,在右侧是一个负责用户的头像。上图中看不到,在鼠标悬停在右上角时还会有一个选项菜单。这个菜单让我们可以修改卡片的颜色提示等。

我们将使用这种更复杂的结构来作为借阅看板卡片的参照。

设计看板视图

我们将改进一直以来开发的library_checkout模型,为图书借阅添加看板视图。为此我们使用一个新文件library_checkout/views/checkout_kanban_view.xml。需要在manifest.py文件的 data 键最下方添加这个文件。在library_checkout/views/library_menu.xml文件中,可以看到借阅菜单项使用的窗口操作。需要对其修改来启用本文中添加的视图类型:

    <act_window id="action_library_checkout"
        name="Checkouts"
        res_model="library.checkout"
        view_mode="kanban,tree,form,activity,calendar,graph,pivot" />

这里我们修改了菜单操作来在view_mode列表的最前面添加了kanban,来让它成为默认的视图模式。然后我们来添加kanban视图记录。与其它视图基本相同,除了 arch 字段内,最外层 XML元素为。下一步创建实际使用的 XML 文件library_checkout/views/checkout_kanban_view.xml来放置这个惊艳的看板视图:

<?xml version="1.0"?>
<odoo>
    <record id="library_checkout_kanban" model="ir.ui.view">
        <field name="model">library.checkout</field>
        <field name="arch" type="xml">
            <kanban>

            </kanban>
        </field>
    </record>
</odoo>

在使用看板视图前,我们需要为图书借阅模型添加几个字段。

优先级、看板状态和颜色

除阶段外,看板中还有一些常用和有用的字段:

编辑library_checkout/models/library_checkout.py文件来在我们的模型中添加这些字段:

class Checkout(models.Model):
...
    priority = fields.Selection(
        [('0', 'Low'),
        ('1', 'Normal'),
        ('2', 'High')],
        'Priority',
        default='1')
    kanban_state = fields.Selection(
        [('normal', 'In Progress'),
        ('blocked', 'Blocked'),
        ('done', 'Ready for next stage')],
        'Kanban State',
        default='normal')
    color = fields.Integer('Color Index')

我们还应该在表单视图中添加这些字段,使用各自的特别组件。kanban_state字段就加在<div class=”oe_title”>之前并在按钮框之后:<field name=”kanban_state” widget=”state_selection” />。priority应添加在name 字段之前,包裹在<h1>元素中:<field name=”priority” widget=”priority” />。color字段一般不出现在表单视图中。

既然借阅模型已有我们所需使用的所有字段,我们可以来写看板视图了。

看板卡片元素

看板视图框架包含一个<kanban>外层元素和以下基础结构:

<kanban default_group_by="stage_id" class="o_kanban_small_column">
                <!-- Fields -->
                <field name="stage_id" />
                <field name="id" />
                <field name="color" />
                <field name="kanban_state" />
                <field name="priority" />
                <field name="message_partner_ids" />

                <!-- Optional progress bar -->
                <progressbar
                    field="kanban_state"
                    colors='{"done": "success", "blocked": "danger"}' />
                <!-- Templates with HTML snippets to use -->
                <templates>
                    <t t-name="kanban-box">
                        <!-- HTML Qweb template -->
                    </t>
                </templates>
            </kanban>

注意在元素中使用了default_group_by=”stage_id”属性,我们用它来让看板默认以 stage 分组,这也是看板通常的分组方式。在简单卡片列表的看板中,如联系人,我们不需要添加该属性,只需使用<kanban>标签即可。<kanban>元素支持以下属性:

然后我们的模板中使用了一组字段。确切地说,只有在 QWeb 表达式中明确使用的字段才需要在这里声明,用以保证从服务端抓取它们的数据。QWeb引擎在处理模板前,仅会在视图中查找 <field name=”…”>来从模型中获取数据。QWeb的属性通常使用不会被检测到的record.field引用方式。正因为如此,需在<templates>之前包含这些字段来让模板处理时有相应字段值可以使用。

ℹ️Odoo 11中的修改 引入了进度条组件。使用的时候在看板列的上方会出现一个颜色条,来提供该列各项的状态数据。在本文前面CRM Pipeline的示例图中可以查看。

<progressbar>有如下属性:

ℹ️Odoo 13中的修改 Odoo 现在使用 Twitter Bootstrap 4,此前版本中使用Bootstrap 3。这些样式在渲染 HTML 的地方通常都可使用,有关Bootstrap更多知识请见官方网站。

下面就来详细了解看板视图中所使用的QWeb模板设计。

看板卡片布局

看板卡片主内容区域在kanban-box模板内定义。这个内容区也可以有一个 footer 底部子容器。卡片右上角还可以添加按钮,点击后打开操作菜单的功能。对于footer区域,应在看板盒子模型底部使用

并添加oe_kanban_bottom CSS 类。还可以通过oe_kanban_bottom_left和oe_kanban_bottom_right CSS 类进一步分割为左、右 footer 区。此外,可通过Bootstrap的pull-left和pull-right类在卡片的任意位置(包括oe_kanban_bottom底部区域)添加向左或向右对齐元素。

 

以下是对看板卡片中QWeb模板的第一次迭代:

                    <t t-name="kanban-box">
                        <!-- Set the Kanban Card color -->
                        <div t-attf-class="
                            oe_kanban_color_#{kanban_getcolor(record.color.raw_value)}
                            oe_kanban_global_click">
                            <div class="o_dropdown_kanban dropdown">
                                <!-- Top-right drop down menu here... -->
                            </div>
                            <div class="oe_kanban_body">
                                <!-- Content elements and fields go here... -->
                            </div>
                            <div class="oe_kanban_footer">
                                <div class="oe_kanban_footer_left">
                                    <!-- Left hand footer... -->
                                </div>
                                <div class="oe_kanban_footer_right">
                                    <!-- Right hand footer... -->
                                </div>
                            </div>
                            <div class="oe_clear" />
                        </div>
                    </t>

这就是看板卡片的整体结构。你可能注意到了在顶部 <div>元素中使用了color字段来动态设置卡片颜色。在后面的部分中我们会讲解t-attf QWeb指令的细节。现在来为主内容区域添加内容:

                            <div class="oe_kanban_body">
                                <div>
                                    <strong>
                                        <a type="open"><field name="member_id" /></a>
                                    </strong>
                                </div>
                                <ul>
                                    <li><field name="user_id" /></li>
                                    <li><field name="request_date" /></li>
                                </ul>
                            </div>

这个模板中大部分都是常规 HTML,但也有渲染字段值的元素和在常规表单视图按钮中使用的 type 属性,此处用在锚文本标签中。 在左部 footer 中插入优先级组件:

                            <div class="o_kanban_record_bottom">
                                <div class="oe_kanban_bottom_left">
                                    <field name="priority" widget="priority" />
                                    <field name="activity_ids" widget="kanban_activity" />
                                </div>
...
                            </div>

这里像我们在表单视图中做的那样添加了priority字段。还添加了一个计划活动的字段,使用kanban_activity特殊组件来显示即将开始活动的指示。

在右部footer中,放入看板状态组件和请求借阅的会员头像:

                                <div class="oe_kanban_bottom_right">
                                    <field name="kanban_state"
                                        widget="kanban_state_selection" />
                                    <img t-att-src="kanban_image(
                                            'library.checkout',
                                            'member_image',
                                            record.id.raw_value)"
                                        t-att-title="record.member_id.value"
                                        t-att-alt="record.member_id.value"
                                        width="24"
                                        height="24"
                                        class="oe_kanban_avatar"
                                    />
                                </div>

补充:原文件使用的 CSS 类oe_kanban_footer,oe_kanban_footer_left和oe_kanban_footer_right经测试不会进行左右对齐,参照 CRM 进行了如上修改

看板状态通过<field>元素和kanban_state_selection组件来进行添加。用户头像使用 HTML 标签插入。图像内容使用QWeb t-att-命令动态生成,后面会详细讲解。这里使用了kanban_image()帮助函数来获取src属性的值。kanban_image() Javascript函数从 Odoo 模型中获取表单并在网页中渲染。有以下属性:

为看板卡片添加选项菜单

看板卡片可在右上角带有一个选项菜单。通常的操作有编辑或删除记录,但也可以为其添加和按钮调用的同样操作。还有一个设置卡片颜色的组件。以下是oe_kanban_content顶部添加的选项菜单的基础代码:

                            <div class="o_dropdown_kanban dropdown">
                                <a class="dropdown-toggle btn"
                                    data-toggle="dropdown" role="button"
                                    aria-label="Dropdown menu"
                                    title="Dropdown menu"
                                    href="#">
                                    <span class="fa fa-ellipsis-v" />
                                </a>
                                <div class="dropdown-menu" role="menu">
                                    <!-- Edit and Delete actions, if available: -->
                                    <t t-if="widget.editable">
                                        <a role="menuitem" type="edit" class="dropdown-item">Edit</a>
                                    </t>
                                    <t t-if="widget.deletable">
                                        <a role="menuitem" type="delete" class="dropdown-item">Delete</a>
                                    </t>
                                    <!-- Color picker option -->
                                    <ul class="oe_kanban_colorpicker" data-field="color" />
                                </div>
                            </div>

下拉菜单基本上是由带有<a>标签的<li> HTML 列表元素组成。Edit 和 Delete 这类选项需要满足指定条件下才会出现。这通过QWeb的t-if命令来实现。本文后续会详细讲解QWeb的命令。widget全局变量表示一个KanbanRecord() JS 对象,负责渲染当前看板卡片。有两个非常有用的属性:widget.editable和widget.deletable,让我们可以检查相应的操作是否可用。

可以看到如何根据记录字段值来显示或隐藏选项,Set as Done仅在未设置is_done 字段时才会显示。最后一个选项添加颜色拾取器组件来使用 color 数据字段选择或修改卡片背景色。因此,除<button>元素外,<a>也可用于运行Odoo 操作。

看板视图中的操作

在QWeb模板中,用于超链的标签可带有一个 type 属性。它设置链接执行的操作类型,这样链接和常规表单中的按钮可进行同样的操作。和表单视图一样,操作类型可以是action或object,并应带有一个 name 属性来标识所要执行的具体操作。此外,还有以下操作类型可以使用:

QWeb 模板语言

QWeb会查找模板中的特殊指令并替换掉动态生成的 HTML。这些指令是 XML 元素属性,可心用在<div><span><field>等有效标签或元素中。有时我们要使用QWeb指令但不希望放在模板的 XML 元素中。对这种情况,可以使用能带有 QWeb 指令(如t-if或t-foreach)的特殊元素<t>,该元组不会在最终产生的XML/HTML有任何输出。

QWeb指令常使用运算的表达式来根据当前记录值生成不同的结果。有两种不同的QWeb实现:客户端JavaScript和服务端Python。报表和网页使用服务端QWeb的 Python 实现。看板视图使用客户端JavaScript实现。也就是说看板视图中的QWeb表达式应使用JavaScript语法书写,而不是 Python。

在显示看板视图时,内部的步骤大致如下:

QWeb JavaScript 运行上下文

许多QWeb指令使用表达式的运行来生成结果。在看板视图这类客户端的应用中,表达式应使用JavaScript书写。表达式在带有几个有用变量的上下文中进行运行。可用record 对象带有从服务端请求的字段来表示当前记录。字段值可通过raw_value或value属性来获取:

QWeb运行上下文还可在JavaScript网页客户端中引用。要擅用这些需要对网页客户端结构有很好的理解,但这里我们不会进行深入介绍。要进行引用 ,QWeb表达式运行中有以下标识符可以使用:

值得一提的是有些字符是不能在表达式中使用的,比如小于号(<) 。这是因为在 XML 标准中,这些字符具有特殊含义,不应在 XML 内容中使用。反向的>=是一个有效替代方式,但通常是使用以下替代符号来进行不等式运算:

ℹ️前述的比较符号仅用于 Odoo,是引入来解决 XML 格式中的限制的。它们不是 XML 标准的一部分。

字符串替换动态属性– t-attf

我们的看板卡片使用t-attf QWeb指令来为顶级

元素动态设置一个类,这样卡片可根据 color 字段值来显示颜色。为此使用了t-attf- QWeb指令。t-attf-指令使用字符串替换动态生成标签属性。这让像 URL 地址或 CSS 类名这类较大字符串中的部分内容可动态生成。

 

该指令查找表达式代码块进行运行并替换结果。它们通过{{和}} 或#{和}来进行分隔。代码块的内容可以是任意JavaScript表达式并使用QWeb表达式中的任意可用变量,如record和widget。本例中我们还使用了专门提供的kanban_color() JS 函数,用于映射索引值到类颜色名。

作为一个更复杂的示例,我们使用这个指令来动态生成用户的颜色,红色字体表示优先级很高。下面替换看板卡片中的相应代码:

                                    <li t-attf-class="oe_kanban_text_{{
                                        record.priority.raw_value lt '2'
                                        ? 'black' : 'red'}}">
                                        <field name="user_id" />
                                    </li>

这将会根据借阅优先级的值生成class=”oe_kanban_text_red”或class=”oe_kanban_text_black”。请注意看板视图中是有oe_kanban_text_red这个 CSS 类的,但oe_kanban_text_black仅用于演示,实际并不存在。

ℹ️注意JavaScript表达式中使用的lt符号,是<的转义表达式,并不能在XML中使用。

表达式动态属性 – t-att

t-att- QWeb指令通过运行表达式动态生成属性值。我们的看板卡片中使用它来为标签动态生成属性,title 属性使用以下表达式动态渲染:

t-att-title="record.member_id.value"

.value字段返回在屏幕上显示的值。对于many-to-one字段,这通常是相关记录的 name 值。对于用户则是用户名。运行之后在鼠标悬停于图像上时会显示相应的用户名。

在表达式运行的结果值为假时,就不会渲染该属性。这对于特殊的 HTML 属性非常重要,比如 input 字段中的 checked,即便在没有属性值时也会有显示效果。

循环 – t-foreach

通过循环遍历来重复同一 HTML 代码块。我们可使用它来添加记录 follower 的头像。让我们先来仅渲染记录的partner ID:

<t t-foreach="record.message_partner_ids.raw_value" t-as="rec">
    <t t-esc="rec" />;
</t>

t-foreach指令接收一个JavaScript表达式,运行来遍历集合。在大多数情况下,这会是 一个to-many关联字段的名称。与t-as指令一同使用来设置用于引用遍历各项的名称。下面使用的t-esc指令运行所提供的表达式,本处仅为 rec 变量名,将其渲染为已转译的安全 HTML。

在上例中,我们遍历了存储在message_partner_ids 字段中的 follower。因为在看板卡片上的空间有限,我们使用JS 的slice()函数来限定所显示的follower数量,如下所示:

t-foreach="record.message_partner_ids.raw_value.slice(0, 3)"

rec变量存储每个遍历值,本例中为partner ID。这样我们可以将循环改写为:

<t t-foreach="record.message_partner_ids.raw_value.slice(0,3)" t-as="rec">
    <img t-att-src="kanban_image('res.partner', 'image_128', rec)"
        class="oe_avatar" width="24" height="24" alt="" />
</t>

比如可将其添加在右侧 footer 的用户头像旁。还包含一些帮助变量,它们的名称以t_as 中定义的变量名为前缀。本例中使用了rec,因此可用的帮助变量如下:

例如可通过如下代码去除ID 列表最后逗号:

<t t-foreach="record.message_parter_ids.raw_value.slice(0, 3)"
    t-as="rec">
    <t t-esc="rec" />
    <t t-if="!rec_last">;</t>
</t>

条件判断 – t-if

我们的看板视图在卡片选项菜单中使用了t-if指令来根据不同条件显示不同选项。t-if指令在客户端渲染看板视图时需传入在 JS 中运行的表达式。标签和其内容仅在条件运行值为true 时才会渲染。作为示例,仅在借出有值时显示图书借出数量,在request_date字段后加入如下代码:

                                    <t t-if="record.num_books.raw_value gt 0">
                                        <li><field name="num_books" /> books</li>
                                    </t>

我们使用了元素,这样在条件为 false 时,元素不会有任何输出。在为 true 时,仅会渲染其所包含的

标签:11,kanban,视图,使用,看板,QWeb,模板
来源: https://www.cnblogs.com/pushuiyu/p/15317430.html