第十三章 关系字段

关系字段的视图组成相对于基础字段来说可能要复杂一些, 常见的关系字段如Many2one, One2many和Many2many都有自己的一套显示逻辑, 这些部件有相同的地方也会有不同的地方, 本章就来揭示这几种关系字段的视图渲染行为特性.

Many2one

Many2one字段在视图上的显示是一个下拉框式的选择器,用户可以选择相应的值,或者使用快速创建和编辑功能创建一条新的记录.

如果想要Many2one的行为类似Selection, 可以使用wiget=selection部件,将其Selection化.

如果想要禁用快速创建和编辑功能, 有两种实现方式, 一种是将该Many2one的宿主对象的创建和编辑权限去掉, 另外一种则是使用options属性,将快速编辑和创建去掉:

<field name="many2one_field" options="{'no_create_edit':True}">
  • no_create: 禁止快速创建
  • no_edit: 禁止快速编辑
  • no_create_edit: 禁止快速创建和编辑
  • no_open: 禁止打开

X2Many

odoo中的One2Many和Many2Many可以被统称做X2Many, 在实际实现过程中, One2ManyField和Many2ManyField也都是从X2ManyField继承而来的.

快速编辑特性

odoo15.0中新增了一个"快速编辑特性", 该特定可以让用户在不点击编辑按钮的情况下切换到编辑模式. X2Many类型的字段的tree视图就是快速编辑的一个使用场景, 用户在X2Many的tree视图中直接点击即可以进行编辑.

该特性的实现基于新增的_canQuickEdit属性, 我们在X2Many的初始化属性中找到了如下代码:

if (arch) {
    this.activeActions.create = arch.attrs.create ?
                                    !!JSON.parse(arch.attrs.create) :
                                    true;
    this.activeActions.delete = arch.attrs.delete ?
                                    !!JSON.parse(arch.attrs.delete) :
                                    true;
    this.editable = arch.attrs.editable;
    this._canQuickEdit = arch.tag === 'tree';
} else {
    this._canQuickEdit = false;
}

由此我们可以知道, X2ManyField的tree节点都会开始快速编辑特性,因此One2Many和Many2Many都会有此特性.

One2many

One2many在视图中默认的渲染结果是一个树形列表, 该树形列表类似与树形视图中的渲染效果但是又有所不同, 其区别点在于:

  1. 树形视图中的列表可以进行分组, 而One2many字段的列表不可以被分组
  2. 树形视图中的列表带有搜索控件, 而One2many字段的列表不可以被搜索
  3. 树形视图中的创建和编辑可以使用create和edit树形进行控制,而One2many字段的列表不可以被控制.

对于X2many类型的字段, 如果用户拥有创建权限, 那么默认情况下,在树形列表的最后一行会有一个"添加新的一行"的超链接, 用户点击该连接就可以快速创建一条新的记录.

创建的新记录既可以在行内直接编辑也可以以弹窗的方式在模态窗口中创建, 控制这两种显示形式的特性是tree节点的editable属性:

<tree editable="top">
    ...
</tree>
  • top: 以模态方式(Form)显示
  • bottom: 以行内编辑的模式显示

如果想要禁止"添加新的一行", 可以通过一下的方式:

  • 该字段设置为readonly属性, 其缺点是所有记录都将不可创建不可编辑
  • options属性中将create设置为false/0
  • 该字段属性中设置can_create属性为false/0

如果想要禁止其编辑One2many字段, 可以使用下面的方式:

  • readonly属性
  • options中的edit属性设置为false/0
  • 字段属性中设置can_write为false/0

如果想要禁止其打开窗口, 可以设置下面的属性:

  • options中的no_open属性设置为false/0

Many2many

Many2many字段与One2many字段基本行为上类似, 只是个别地方的行为有差异.

如果想要禁用Many2many字段的"添加新的一行", 不能使用create属性,而应当使用link属性替代.

options中支持的操作有: create delete link unlink.

X2many的options属性从14.0开始支持.

Reference

Reference是相对比较特殊的一个字段, 乃至odoo在顶层的数据加载过程中都对它进行了特殊化的处理.

我们在第三章提到过, 数据加载过程中使用read方法读取到数据以后, 回对Reference类型的字段进行特殊化的处理. 这个特殊化的处理就是指,页面再渲染Reference类型的字段时,会调用它的rpc方法name_get来获取可读化的文本, 而非其数据库存储值: model_name,id

这个过程的载体是_fetchReference方法:

_fetchReference: function (record, fieldName) {
    var self = this;
    var def;
    var value = record._changes && record._changes[fieldName] || record.data[fieldName];
    var model = value && value.split(',')[0];
    var resID = value && parseInt(value.split(',')[1]);
    if (model && model !== 'False' && resID) {
        def = self._rpc({
            model: model,
            method: 'name_get',
            args: [resID],
            context: record.getContext({fieldName: fieldName}),
        }).then(function (result) {
            return self._makeDataPoint({
                data: {
                    id: result[0][0],
                    display_name: result[0][1],
                },
                modelName: model,
                parentID: record.id,
            });
        });
    }
    return Promise.resolve(def);
},

results matching ""

    No results matching ""