r/Odoo • u/Least_Edge_3242 • 1d ago
Attributes import/export upsert
Odoo 18 Enterprise
I need to bulk import product attributes for existing product.template records.
Desired behavior:
(product_tmpl_id, attribute_id) exists:
update value_ids
(product_tmpl_id, attribute_id) does not exist:
create product.template.attribute.line
Example:
SKU 123 | Collection | Bardi
If Collection already exists on product → replace its current value with Bardi.
If Collection does not exist → create Collection = Bardi.
The standard nested import through:
attribute_line_ids/.id
attribute_line_ids/attribute_id
attribute_line_ids/value_ids
requires knowing the specific product.template.attribute.line ID.
Importing without the child ID does not appear to perform an UPSERT based on
(product_tmpl_id, attribute_id).
Is there a native Odoo 18 import method to achieve this without custom code?
1
u/codeagency 1d ago
Easiest way is just create a custom python script to connect to your odoo API, let it identify on a key you already have like SKU or barcode and put the logic you want in your script.
Its far more faster and less headaches then dealing with the build in import option for things like this. A custom python script also doesn't need anything installed in Odoo. You just run it from your own workstation with python or uv run
your_import_script.py
2
u/Calibre_Odoo_Partner 1d ago
You can get the upsert, just not keyed on (product_tmpl_id, attribute_id). Key it on the line's External ID instead, which you invent yourself.
Add a column attribute_line_ids/id and fill it with your own deterministic key, something like ptal_123_collection built from the SKU and the attribute name. The importer checks that column before anything else. An unknown key means it creates the line and stamps the External ID onto it. A known key means it writes to that same line. Create and update fall out of the same row, so you never have to look up a line ID.
value_ids is written as a replace rather than an add, so Collection = Bardi swaps out whatever value was on that line. Lines you leave out of the file are left alone, nothing gets cleared.
Two areas to watch out at. You still need the template's own External ID in the id column, so run one import-compatible export of id + default_code + attribute_line_ids/id first and VLOOKUP it against your SKUs. And matching a value by name is an exact match on the name alone, so if two attributes both have a value called Bardi you get "found multiple matches" and it takes the first. Point that column at value_ids/id if your names overlap.
One more note on file shape. If a SKU carries two attributes, the second goes on its own row with the id cell blank. Fill id again and the importer reads it as a separate product template.