You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Context加载One2many字段?示例场景求技术协助

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:46:45