Skip to main content
iVentureTeam

auto_save_res_partner

A child list that saves its parent before letting you add a row. Seven lines of code for a problem that otherwise produces confusing errors on brand new contacts.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated September 2, 20265 min read
Technical nameauto_save_res_partner
Field typesone2many, many2many
Viewsform, with an embedded list
Moduleaccount, present wherever Invoicing or Accounting is installed
Used in core1 occurrence, a partner tax list in the Argentinian withholding localization
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0
No-code setupNo. It is a view XML widget for child lists that need a saved parent
Alternativesone2many, payment_term_line_ids, many2many, many2many_tags_banks

What the autosaving child list does

Adding a child record to an unsaved parent is a recurring awkwardness in Odoo. The framework can hold the child in memory and write both together, but only when the child does not need anything the parent has not got yet, and the most common thing it has not got is a database id.

Some child records do need one. Anything that will be looked up, computed against or validated server side by parent id has to be attached to something real. On a brand new contact, that means the contact has to exist first.

This widget removes the awkwardness by saving the parent when the user clicks to add a row, and only then adding it. From the user's point of view nothing happens except that the contact is now saved.

What this means for your team

The alternative to this widget is worse than it sounds. Without it, a user filling in a new contact and adding a child line gets either a confusing server error or a row that silently fails to link, and neither points at the real cause, which is that the contact was never saved.

The trade is that the contact is committed earlier than the user expected. On a contact form that is usually fine, because a half-filled contact is still a useful record, but it is worth knowing if your process treats the form as a draft until everything is entered.

The general pattern is worth keeping in mind for custom work: where a child needs a real parent, save on the add action rather than trying to explain the constraint to the user afterwards.

Supported options in Odoo 19

The widget declares no supported options, and neither does the x2many descriptor it spreads: the options dictionary is forwarded to the embedded list as CRUD settings. The controls that matter are attributes on the inner list, shown below and verified against the Odoo 19.0 source.

OptionTypeWhat it does
editablestring (list attribute)Set on the embedded list. Governs inline editing of the child rows, independently of the save on add.
createboolean (list attribute)Set on the embedded list. Turning it off removes the add action, and with it the only thing this widget changes.(default: true)
deleteboolean (list attribute)Set on the embedded list. Deletion is untouched by the widget.(default: true)

The save is unconditional on the add action. There is no option to skip it, and it applies to the model's root record rather than to the field's own record, so on a nested form it is the outermost record that gets saved.

Working examples

The core usage, trimmed

<field name="l10n_ar_partner_tax_ids" nolabel="1"
       colspan="2" widget="auto_save_res_partner">
  <list editable="bottom"> ... </list>
</field>

An ordinary editable child list. The only difference is what happens when the add link is clicked.

Reusing it elsewhere

<field name="my_child_ids"
       widget="auto_save_res_partner">
  <list editable="bottom"> ... </list>
</field>

Nothing in the widget is partner-specific despite its name, so any child list needing a saved parent benefits.

The ordinary child list

<field name="my_child_ids">
  <list editable="bottom"> ... </list>
</field>

Adds a row without saving, which is right whenever the child does not need a real parent id.

One awaited save, and what it does not cover

The whole widget is one overridden method. It awaits a save of the model's root record, then calls the parent implementation with the same arguments, so the row is added exactly as it normally would be, just afterwards.

Two consequences follow. The save is of the root record, not of the field's own record, which matters on a nested form: the outermost record is what gets committed. And because the save is awaited, a failure propagates and the row is never added, so an invalid contact produces the ordinary validation error rather than a half-created child.

What the widget does not do is equally worth noting. It does not save when an existing row is edited, it does not save after the row is filled in, and it does not intervene in deletion. Only the add action is touched.

Its name and location are slightly misleading. The file sits in the accounting module's partner bank folder, suggesting bank accounts, but the only core usage is a tax list on the contact form in an Argentinian localization. The behavior is entirely generic.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Byte-identical to Odoo 19 on the development branch.
Odoo 19.0VerifiedVerified against the shipped source. Unchanged in substance since Odoo 17.
Odoo 18.0VerifiedIdentical behavior.
Odoo 17.0VerifiedFirst version.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. Nothing to do. The widget arrived in Odoo 17 and is unchanged in substance through Odoo 19; the only difference is the module marker comment Odoo 19 dropped across the codebase.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The development branch is unstable and this may still change; we re-verify the page after release.

Byte-identical. The file on the development branch matches Odoo 19 exactly, which is unsurprising for a widget with one overridden method and no props of its own.

Common problems and fixes

SymptomCause and fix
The contact saved itself when I added a lineIntended. The widget saves the root record before adding the row so the child has a real parent. Expected. Fill the contact's required fields before adding child lines.
The row is not added and I get a validation errorThe save failed, and the widget awaits it before adding. Fix the reported field on the parent, then add the row again.
Editing an existing row does not save the parentOnly the add action is overridden. Expected. Save the form as usual.
The wrong record was saved on a nested formThe widget saves the model's root record, not the field's own record. Expected. Use it on a top-level form where that is the intended record.
Nothing is different from an ordinary listThe parent was already saved, so the extra save had nothing to do. Nothing to fix; the behavior only shows on a new record.
Missing widget errorThe accounting module is not installed in that database. Install Invoicing or Accounting, or use a plain child list.

Autosaving child list vs the alternatives

WidgetBest forKey difference
auto_save_res_partnerChild lists whose new rows need the parent to exist in the databaseAwaits a save of the root record before adding a row, and touches nothing else
one2manyChild lists whose rows do not need a saved parentAdds the row immediately, with no save
payment_term_line_idsLists whose new rows must not be discardedSolves the abandonment problem rather than the unsaved parent problem
many2manyLinking existing recordsNo creation, so the question does not arise
many2many_tags_banksPartner bank accounts as tagsSaves on mount rather than on add, and renders tags

Use a plain child list wherever the child does not need a real parent id, which is most cases. Where it does, this widget is the smallest fix; the alternative, making the user save first and telling them why, is more explicit but costs a step every time. If the child list itself should keep rows alive once added, the payment terms widget solves a different problem in the same area.

Frequently asked questions

Why does the contact save when I add a line?+
Because the child record needs a real parent id. The widget awaits a save of the root record and only then adds the row, which avoids the confusing errors an unsaved parent produces.
What happens if the save fails?+
The row is not added. The save is awaited, so a validation error on the parent surfaces normally and nothing half-created is left behind.
Does it save when I edit an existing row?+
No. Only the add action is overridden; everything else behaves like an ordinary child list.
Is it specific to partner bank accounts?+
No, despite where the file lives. Its only core usage is a tax list on the contact form in an Argentinian localization, and the behavior is entirely generic.
Which versions have it?+
Odoo 17 onwards, unchanged in substance, and byte-identical on the Odoo 20 development branch.

Localizations that behave like the rest of your Odoo

Country-specific taxes, withholdings and reporting bring their own screens, and they are only as good as the setup underneath. We implement and adapt Odoo fiscal localizations on versions 16 through 19.

Book a free consultation

How this page was produced

The single overridden add action, its await of the model root's save and the absence of any other intervention were read from auto_save_res_partner_bank.js on the Odoo 19.0 branch, with the inherited behavior read from the x2many field in web. The usage comes from the Argentinian withholding localization's partner view. Version coverage comes from comparing the file across the 17.0 and 18.0 branches and a byte comparison against the public development branch. Spotted an error? Tell us and we will correct the page.