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

Odoo 11 One2many计算字段编辑无法保存问题求助

Why Your Computed Partner Field Isn't Saving Changes

Hey there, let's break down why your computed field isn't sticking after edits—and how to fix this.

First, a quick reminder of how Odoo computed fields work by default: they’re read-only by design. Their values are generated entirely by your compute method, so when you edit one and save, Odoo immediately re-runs that compute logic, overwriting whatever manual change you just made. That’s why your edits vanish after a refresh—they never actually get saved to the database.

The Core Fix: Add an inverse Method

To make a computed field editable, you must define an inverse method that tells Odoo how to translate your manual edits back into changes to the underlying data (like the child_ids you’re working with).

Let’s use a concrete example. Suppose your current field definition looks like this (missing the critical inverse):

my_partners = fields.Many2many(
    'res.partner',
    compute='_compute_my_partners',
    string="My Partners"
)

def _compute_my_partners(self):
    for record in self:
        # Your custom logic to filter child partners
        record.my_partners = record.child_ids.filtered(lambda p: p.category_id.id == 123)

To make this field editable and saveable, update it with an inverse parameter and implement the sync logic:

my_partners = fields.Many2many(
    'res.partner',
    compute='_compute_my_partners',
    inverse='_inverse_my_partners',  # Add this line
    readonly=False,  # Explicitly allow editing
    string="My Partners"
)

def _compute_my_partners(self):
    for record in self:
        record.my_partners = record.child_ids.filtered(lambda p: p.category_id.id == 123)

def _inverse_my_partners(self):
    for record in self:
        # Step 1: Remove existing child partners that don't match your filter
        existing_matches = record.child_ids.filtered(lambda p: p.category_id.id == 123)
        record.child_ids = (record.child_ids - existing_matches) | record.my_partners
        
        # Step 2: Ensure selected partners have this record as their parent
        for partner in record.my_partners:
            if partner.parent_id != record:
                partner.parent_id = record

The inverse method’s job is to take your manual input and apply it to the actual stored data (in this case, child_ids and the partners’ parent_id). Tweak this logic to match your specific business rules.

Alternative Approaches If Computed Fields Feel Clunky

If the computed field + inverse approach doesn’t fit your use case, here are two solid alternatives:

1. Regular Many2many Field with Onchange/Constraints

Define a standard editable Many2many field, then use onchange methods or constraints to keep it in sync with child_ids:

my_editable_partners = fields.Many2many('res.partner', string="My Partners")

@api.onchange('my_editable_partners')
def _onchange_my_partners(self):
    # Auto-set parent ID for selected partners
    if self.my_editable_partners:
        for partner in self.my_editable_partners:
            partner.parent_id = self

@api.constrains('my_editable_partners')
def _check_partners(self):
    # Optional: Ensure only valid child partners are selected
    invalid_partners = self.my_editable_partners.filtered(lambda p: p.parent_id != self)
    if invalid_partners:
        raise ValidationError("Selected partners must be children of this record.")

2. Server Actions/Automation

For simpler sync logic, set up an automated action (under Settings > Technical > Automation > Automated Actions) that triggers when the record saves. This action can update child_ids based on your editable field’s value without writing custom code.


内容的提问来源于stack exchange,提问作者foo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:52:45