扫码阅读
手机扫码阅读

Odoo丨手把手教你灵活控制表单明细的创建与删除!

349 2023-09-21


Odoo

神州数码云基地

在 Odoo 上的尝试、调研与分享



本期内容

如何创建和删除表单明细

我们知道,在Odoo页面上,控制的最小单位是字段,可通过Odoo提供的属性,控制字段的必填、只读、隐藏等功能。

但对于form表单下的tree视图,总体来讲仍是一个字段,可通过tree视图的属性create="1" delete="1" 来控制明细信息的创建和删除,但不能单独控制具体某一行的属性。


于是,我们引发了以下思考:

能不能在页面上设置一个控制开关,开启时,明细行就能添加和删除,关闭时就不能;


如果能通过开关字段控制明细行属性,能否通过字段带出明细数据,并禁止添加和删除,实现不只是只读,而是可编辑模式?

带着上述疑问,本期我们就一起来看看,如何在Odoo上实现灵活创建和删除表单页明细。

表单明细的创建与删除

根据主表字段带出明细信息

首先,在后端使用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          #给关联字段赋值

通过以上操作,表单带出问题就顺利解决了⬇

根据主表字段控制明细表的添加和删除功能

如果说带出功能是后端的问题,那么隐藏添加明细和删除就是前端来控制的


明细表虽是表数据,但是在主模型里,依然是一个一对多的字段,只要是字段就能使用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中灵活实现表单功能的思路。

在日常的操作中,如果遇到明细表单的创建,删除相关的问题,不妨试试上述分享的方法吧。

关于在Odoo中创建和删除

明细表单的分享就到这儿啦~

如果你有更好的办法或疑问

欢迎加入社群一起讨论哦⬇

本期作者

张备

想要了解更多,点击 查看原文