如何通过Context加载One2many字段?示例场景求技术协助
我来帮你梳理下这个需求的实现思路,结合Odoo的上下文和ORM机制,咱们分场景来解决:
首先得明确你的核心需求:把父模型中已过滤的field_parent记录集,加载到子模型关联的One2many字段field_child里。你给出的示例是传递单个Many2one值,但要处理多个记录的话,得调整上下文的用法和关联字段的赋值逻辑。
方案1:通过上下文传递ID列表,设置One2many默认值
如果是在打开子表单/列表时,直接把父模型已过滤的field_parent记录预加载到field_child里,可以通过上下文传递记录ID,再结合默认值方法来实现:
第一步:在父视图的One2many字段中传递上下文
在父模型的视图XML里,给One2many字段加上上下文,把已过滤的field_parent的ID列表传进去:
<field name="field_child" widget="one2many_list" context="{'default_parent_record_ids': parent.field_parent.ids}"/>
这里field_child是父模型关联子模型的One2many字段,default_parent_record_ids是我们自定义的上下文键,用来存父记录的ID列表。
第二步:在子模型中接收上下文并设置默认值
在子模型的Python代码里,重写default_get方法,读取上下文里的ID列表,用Odoo的ORM命令格式给关联字段赋值:
from odoo import models, fields, api class ChildModel(models.Model): _name = 'child.model' _description = '子模型' parent_id = fields.Many2one('parent.model', string='父记录') # 如果是关联多个父记录,用Many2many: parent_record_ids = fields.Many2many('parent.model', string='已过滤父记录') @api.model def default_get(self, fields_list): res = super().default_get(fields_list) # 读取上下文传递的ID列表 parent_ids = self.env.context.get('default_parent_record_ids', []) if parent_ids: # 用(6,0, ids)命令设置Many2many的默认值,替换为指定ID的记录 res['parent_record_ids'] = [(6, 0, parent_ids)] # 如果是One2many关联单个父记录,循环创建子记录: # res['field_child'] = [(0, 0, {'parent_id': pid}) for pid in parent_ids] return res
方案2:通过上下文过滤One2many的显示范围
如果你只是希望在父视图的One2many字段中,只显示和已过滤field_parent关联的子记录,可以直接通过domain结合上下文来实现:
直接在One2many字段设置domain
最简单的方式是在视图里直接写domain,引用父模型的field_parentID列表:
<field name="field_child" widget="one2many_list" domain="[('parent_id', 'in', parent.field_parent.ids)]"/>
这样field_child只会显示那些parent_id在已过滤父记录中的子记录。
动态通过上下文传递domain
如果过滤逻辑更复杂,需要动态调整,可以把domain放到上下文里:
<field name="field_child" widget="one2many_list" context="{'child_filter_domain': [('parent_id', 'in', parent.field_parent.ids)]}"/>
然后在子模型的视图中,读取上下文里的domain:
<field name="parent_id" domain="context.get('child_filter_domain', [])"/>
方案3:用onchange方法动态同步已过滤记录
如果需要在父模型的field_parent变化时,自动更新field_child的内容,可以用onchange方法实现实时同步:
from odoo import models, fields, api class ParentModel(models.Model): _name = 'parent.model' _description = '父模型' field_parent = fields.Many2many('some.model', string='已过滤记录') field_child = fields.One2many('child.model', 'parent_id', string='子记录') @api.onchange('field_parent') def _onchange_field_parent(self): if self.field_parent: # 循环已过滤的父记录,创建对应的子记录 child_records = [] for parent_rec in self.field_parent: child_records.append((0, 0, {'parent_id': parent_rec.id})) self.field_child = child_records else: # 清空子记录 self.field_child = [(5, 0, 0)]
这个方法会在field_parent的内容变化时,自动更新field_child,把所有已过滤的父记录关联到子记录里。
几个关键注意点
- 确保
parent.field_parent是记录集类型(比如Many2many、One2many字段,或者通过domain筛选后的记录),这样.ids才能正确获取到ID列表。 - Odoo的关联字段(One2many/Many2many)必须用ORM命令格式赋值:比如
(6,0, ids)表示替换为指定ID的记录,(0,0, vals)表示创建新记录,(5,0,0)表示清空所有记录,这些是Odoo的标准用法,不能直接赋值ID列表。 - 如果是在表单视图中动态加载,
onchange方法的实时性会比上下文传递更好,适合需要即时同步的场景。
内容的提问来源于stack exchange,提问作者a.CHOURAR

