文章目录
- 一、前言
- 二、表单明细的创建与删除
- 1.根据主表字段带出明细信息
- 2.根据主表字段控制明细表的添加和删除功能
- 三、总结
一、前言
我们知道,在Odoo页面上,控制的最小单位是字段,可通过Odoo提供的属性,控制字段的必填、只读、隐藏等功能。
但对于form表单下的tree视图,总体来讲仍是一个字段,可通过tree视图的属性create=“1” delete=“1” 来控制明细信息的创建和删除,但不能单独控制具体某一行的属性。
于是,我们引发了以下思考:
能不能在页面上设置一个控制开关,开启时,明细行就能添加和删除,关闭时就不能;
如果能通过开关字段控制明细行属性,能否通过字段带出明细数据,并禁止添加和删除,实现不只是只读,而是可编辑模式?
带着上述疑问,本期我们就一起来看看,如何在Odoo上实现灵活创建和删除表单页明细。
二、表单明细的创建与删除
1.根据主表字段带出明细信息
首先,在后端使用onchange监听能带出明细的字段,确保该字段数据内容正确。同时拿到数据之后,通过模型,查询要带出的数据,对数据进行格式化。
然后根据Odoo默认的关联关系来绑定,就能实现明细的动态创建了。
举个例子,模型test是主表,其中name_rel就是关联字段,通过姓名带出信息:
那么,具体的后端代码实现可以参考如下:
@api.onchange('name_a') #监听姓名字段
def _name_a(self):
args_list = []
self.name_rel = None #把关联关系接触,每次触发清楚上次的明细
if self.name_a:
purchase_detail = [{ #可以通过sql查询,或者接口获取,拿到想要的明细数据
'name_b': '打篮球',
'time_b': '2年'
}]
for detail in purchase_detail:
num = 1
args = {
'name_b': detail['name_b'],
'time_b': detail['time_b'],
}
args_list.append((0, 0, args)) #建立odoo规定的关联关系!!
num += 1
self.res_sale_product_detail = args_list #给关联字段赋值
通过以上操作,表单带出问题就顺利解决了⬇
2.根据主表字段控制明细表的添加和删除功能
如果说带出功能是后端的问题,那么隐藏添加明细和删除就是前端来控制的。
明细表虽是表数据,但是在主模型里,依然是一个一对多的字段,只要是字段就能使用widget控制,我们顺着这条思路进行探索。
在研磨源码之后,我们发现页面每次改动之后,都是会调用前端基础控件FieldX2Many的reset方法;
虽然我们是拓展FieldOne2Many方法,但是FieldOne2Many方法也是拓展于基础模型FieldX2Many的,所以我们可以直接在新方法里重写reset方法。
当然在起初进入页面时,可以修改基础的init属性,保证页面初始加载,或是动态改变之后,依然能生效。
具体操作代码如下:
var hideCreateDelete = FieldOne2Many.extend({
init: function (parent, name, record, options) {
this._super.apply(this, arguments);
let x = record.data['想要控制的字段'];
var arch = this.view && this.view.arch;
if (x) {
if (arch) {
this.activeActions.create = false;
this.activeActions.delete = false;
this.editable = arch.attrs.editable;
}
} else {
if (arch) {
this.activeActions.create = true;
this.activeActions.delete = true;
this.editable = arch.attrs.editable;
}
}
},
reset: function (record, ev, fieldChanged) {
let x = record.data['想要控制的字段'];
const oldCanCreate = this.canCreate;
const oldCanDelete = this.canDelete;
const oldCanLink = this.canLink;
const oldCanUnlink = this.canUnlink;
var arch = this.view && this.view.arch;
if (x) {
this.activeActions.create = false;
this.activeActions.delete = false;
this.editable = arch.attrs.editable;
} else {
this.activeActions.create = true;
this.activeActions.delete = true;
this.editable = arch.attrs.editable;
}
this._computeAvailableActions(record);
const actionsChanged =
this.canCreate !== oldCanCreate ||
this.canDelete !== oldCanDelete ||
this.canLink !== oldCanLink ||
this.canUnlink !== oldCanUnlink;
// If 'fieldChanged' is false, it means that the reset was triggered by
// the 'resetOnAnyFieldChange' mechanism. If it is the case, if neither
// the modifiers (so the visible columns) nor the available actions
// changed, the reset is skipped.
if (!fieldChanged && !actionsChanged) {
var newEval = this._evalColumnInvisibleFields();
if (_.isEqual(this.currentColInvisibleFields, newEval)) {
this._reset(record, ev); // update the internal state, but do not re-render
return Promise.resolve();
}
} else if (ev && ev.target === this && ev.data.changes && this.view.arch.tag === 'tree') {
var command = ev.data.changes[this.name];
// Here, we only consider 'UPDATE' commands with data, which occur
// with editable list view. In order to keep the current line in
// edition, we call confirmUpdate which will try to reset the widgets
// of the line being edited, and rerender the rest of the list.
// 'UPDATE' commands with no data can be ignored: they occur in
// one2manys when the record is updated from a dialog and in this
// case, we can re-render the whole subview.
if (command && command.operation === 'UPDATE' && command.data) {
var state = record.data[this.name];
var fieldNames = state.getFieldNames({viewType: 'list'});
this._reset(record, ev);
return this.renderer.confirmUpdate(state, command.id, fieldNames, ev.initialEvent);
}
}
this._reset(record, ev);
return this._super.apply(this, arguments);
},
});
想要实现按条件显示添加明细和删除,我们就要从内部理解关联字段的属性。
this.canCreate是可以创建的,同理canDelete就是能够删除的。
最后我们给明细字段绑定上自定义的widget,一起在页面上见证成果:
通过我们的设置,在编辑模式下,添加明细和删除实现了隐藏。
三、总结
以上就是今天关于在Odoo中灵活实现表单功能的思路。
在日常的操作中,如果遇到明细表单的创建,删除相关的问题,不妨试试上述分享的方法吧。