Odoo13看板视图跨状态拖动记录时必填字段未校验问题咨询
Odoo13 看板视图拖动记录跨列流转时触发必填校验的实现方案
Odoo13默认逻辑里,form视图上配置的字段必填规则仅在表单编辑保存时生效,看板视图下拖动记录跨状态列流转时,走的是单字段快速写入逻辑,不会加载form视图的校验规则,所以会出现必填字段为空也能改状态的问题。可以通过以下两层方案解决:
后端模型层加全局校验(必做,从根源解决绕过问题)
视图层的required属性本质是前端交互限制,所有非表单入口的操作(看板拖动、列表行内编辑、接口调用、批量修改)都不会触发这类校验,必须把必填规则写到模型层,才能保证所有写入场景都能触发校验。
参考实现代码:from odoo import models, fields, api from odoo.exceptions import ValidationError class YourBusinessModel(models.Model): _inherit = 'your.actual.model.name' # 简单固定/条件必填直接写在字段定义上,写入时自动校验 # 例:状态为done时,处理方案、完成时间为必填 solution = fields.Text(string="处理方案", required=lambda self: self.state == 'done') finish_time = fields.Datetime(string="完成时间", required=lambda self: self.state == 'done') # 复杂多字段联动校验用约束方法实现 @api.constrains('state', 'solution', 'finish_time', 'handler_id') def _check_state_required_fields(self): for rec in self: if rec.state == 'done': missing_fields = [] if not rec.solution: missing_fields.append('处理方案') if not rec.finish_time: missing_fields.append('完成时间') if not rec.handler_id: missing_fields.append('处理人') if missing_fields: raise ValidationError(f"记录流转到完成状态前,需补全以下必填项:{','.join(missing_fields)}")写完升级模块后,不管从哪个入口修改状态,只要必填字段为空,就会直接抛出校验提示,阻止状态变更。
前端看板交互优化(可选,提升使用体验)
后端校验是在写入时触发,报错时记录已经完成拖动动作后再弹提示,如果需要在拖动落位前就完成校验、不符合要求直接退回原位置,可以扩展看板组件的拖动事件,加一层前端前置校验。
参考实现代码(存放到自定义模块的static/src/js/kanban_check.js路径下,并在模块资源清单中引入):odoo.define('custom_module.kanban_required_validator', function (require) { "use strict"; const KanbanRenderer = require('web.KanbanRenderer'); const core = require('web.core'); const _t = core._t; KanbanRenderer.include({ _onDropRecord: function (event, ui) { const targetState = event.currentTarget.dataset.groupByValue; const recordData = this._getDropRecord(event, ui).state.data; // 配置各状态对应的必填字段 const stateRequiredMap = { 'done': ['solution', 'finish_time', 'handler_id'] }; const needCheckFields = stateRequiredMap[targetState] || []; const missing = []; needCheckFields.forEach(field => { if (!recordData[field]) { missing.push(this.fields[field].string); } }); if (missing.length) { event.preventDefault(); // 将记录退回原位置 ui.placeholder.after(ui.draggable); this.do_warn(_t('校验失败'), _t('流转到当前状态前需填写:') + missing.join('、')); return; } return this._super.apply(this, arguments); } }); });注意:前端校验仅做体验优化,不能替代后端校验,用户可以通过浏览器调试、接口调用等方式绕过前端规则,必须和后端模型层校验搭配使用。
踩坑提示:不要试图只修改视图xml的属性解决问题,所有视图层的规则都只对应当前视图的交互场景,数据层面的校验必须落回模型层实现。
内容的提问来源于stack exchange,提问作者David Santiago Correa Sierra
相关产品推荐
相关产品推荐

