Odoo 16向导中基于模板动态生成字段的实现方法问询
实现Odoo 16 向导动态字段展示
1. 定义向导模型(TransientModel)
创建基于TransientModel的向导模型,包含关联模板的Many2one字段,以及用于存储动态字段值的JSON字段:
from odoo import models, fields, api class DynamicFieldWizard(models.TransientModel): _name = 'dynamic.field.wizard' _description = 'Dynamic Field Wizard' template_ids = fields.Many2one('your.template.model', string='Template', required=True) dynamic_values = fields.Json(string='Dynamic Values', default={}) @api.onchange('template_ids') def _onchange_template_ids(self): # 切换模板时清空之前的动态值 self.dynamic_values = {}
替换your.template.model为实际的模板模型名称,确保该模型包含variables_id的One2many字段(关联变量模型)。
2. 设计向导视图
编写form视图,添加模板选择字段,预留动态字段容器,并引入自定义JS脚本:
<?xml version="1.0" encoding="utf-8"?> <odoo> <record id="dynamic_field_wizard_form" model="ir.ui.view"> <field name="name">dynamic.field.wizard.form</field> <field name="model">dynamic.field.wizard</field> <field name="arch" type="xml"> <form string="Dynamic Field Wizard"> <sheet> <group> <field name="template_ids" required="1" /> <!-- 动态字段容器 --> <div id="dynamic_fields_container" class="mt-3"> <!-- 动态生成的字段将插入此处 --> </div> <!-- 隐藏字段存储动态值 --> <field name="dynamic_values" invisible="1" /> </group> </sheet> <footer> <button name="action_confirm" type="object" string="Confirm" class="btn-primary" /> <button string="Cancel" class="btn-secondary" special="cancel" /> </footer> </form> </field> </record> <!-- 注册向导启动动作 --> <record id="action_dynamic_field_wizard" model="ir.actions.act_window"> <field name="name">Dynamic Field Wizard</field> <field name="res_model">dynamic.field.wizard</field> <field name="view_mode">form</field> <field name="target">new</field> </record> </odoo>
3. 编写前端JS逻辑
创建JS文件,监听template_ids字段变化,动态生成对应数量的输入字段:
odoo.define('dynamic_field_wizard.dynamic_fields', function (require) { "use strict"; var core = require('web.core'); var FormView = require('web.FormView'); var QWeb = core.qweb; FormView.include({ on_loaded: function () { this._super.apply(this, arguments); var self = this; var templateField = this.$el.find('div[name="template_ids"]'); // 初始加载时若已有选中模板,直接生成字段 if (this.datarecord.template_ids) { self._generateDynamicFields(this.datarecord.template_ids[0]); } // 监听模板选择变化 templateField.on('change', function () { var templateId = templateField.find('input').val(); if (templateId) { self._generateDynamicFields(templateId); } else { $('#dynamic_fields_container').empty(); self.datarecord.dynamic_values = {}; } }); }, _generateDynamicFields: function (templateId) { var self = this; // 调用后端获取模板关联的变量数据 this._rpc({ model: 'your.template.model', method: 'read', args: [[templateId], ['variables_id']], }).then(function (templates) { var variables = templates[0].variables_id; var container = $('#dynamic_fields_container'); container.empty(); // 遍历变量生成输入字段 variables.forEach(function (variable) { var variableId = variable[0]; var variableName = variable[1]; // 渲染动态字段模板 var fieldHtml = QWeb.render('DynamicFieldTemplate', { variable_id: variableId, variable_name: variableName, current_value: self.datarecord.dynamic_values[variableName] || "" }); container.append(fieldHtml); // 绑定输入值到dynamic_values字段 container.find('#dynamic_field_' + variableId).on('input', function () { var value = $(this).val(); self.datarecord.dynamic_values[variableName] = value; // 更新隐藏字段的JSON值 self.$el.find('input[name="dynamic_values"]').val(JSON.stringify(self.datarecord.dynamic_values)); }); }); }); } }); // 定义动态字段的QWeb模板 core.qweb.add_template('DynamicFieldTemplate', '<div class="form-group">' + '<label class="col-form-label" for="dynamic_field_{{ variable_id }}">{{ variable_name }}</label>' + '<input type="text" id="dynamic_field_{{ variable_id }}" class="form-control" value="{{ current_value }}"/>' + '</div>' ); return {}; });
替换your.template.model为实际模板模型名称,若变量模型包含字段类型(如选择框、日期),可扩展模板生成对应控件。
4. 注册JS脚本
在模块的__manifest__.py中引入JS文件:
{ # ... 其他模块配置 'assets': { 'web.assets_backend': [ 'your_module_name/static/src/js/dynamic_fields.js', ], }, }
5. 处理确认动作(可选)
若需在确认时处理动态字段值,在向导模型中添加方法:
def action_confirm(self): self.ensure_one() # 读取dynamic_values中的数据执行业务逻辑 for variable_name, value in self.dynamic_values.items(): # 示例:打印变量名和对应值 print(f"Variable: {variable_name}, Value: {value}") return {'type': 'ir.actions.act_window_close'}
核心逻辑说明
- 动态字段值通过JSON字段
dynamic_values存储,避免后端动态创建字段的复杂度 - 前端通过RPC拉取模板关联的变量数据,动态渲染表单控件
- 可根据变量类型扩展生成不同的输入控件(如下拉框、日期选择器)
内容的提问来源于stack exchange,提问作者Mahfujul Hasan
相关产品推荐
相关产品推荐

