Odoo 11 One2many计算字段编辑无法保存问题求助
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

