Most addons have different types of data. Some data simply needs to exist for the module to work properly, other data shouldn't even be changed by the user, while most data is meant to be changed per the user's pleasure and is only provided as a convenience. This recipe will detail how to address the different types. First, we'll write a field in an already existing record, then, we'll create a record that is supposed to be recreated during a module update.
We can enforce different behaviors from Odoo when loading data by setting certain attributes on the enclosing odoo
element or the record
element itself.
<odoo noupdate="1"> <record id="res_partner_packt" model="res.partner"> <field name="name">Packt publishing</field> </record> </odoo>
<odoo noupdate="1"> <record id="book_category_all" model="library.book.category" forcecreate="false"> <field name="name">All books</field> </record> </odoo>
The odoo
element can have a noupdate
attribute, which is propagated to the
ir.model.data records created when reading the enclosed data records for the first time, ending up as a column in this table.
When Odoo installs an addon (called init mode), all noupdate records are written. When you update an addon (called update mode), existing XML IDs are checked to see if they have the noupdate
flag set, and if so, elements trying to write to this XML ID are ignored. This is not the case if the record in question was deleted by the user, which is why you can force not recreating noupdate records also in update mode by setting the flag forcecreate on the record to false
.
You can force init mode by starting your Odoo server with the parameter --init=your_addon
, this way overwriting all existing noupdate records. This will also cause deleted records to be recreated. Note that this can cause double records and related installation errors if a module circumvents the XML ID mechanism, for example, by creating records in Python code called by YAML files.
For modules you write from scratch, you don't need to worry too much about noupdate records in either your own addon or other ones, as long as you only install it after all development is done. But imagine you add a new feature to an existing module that is already out in the wild. Then you might need to set a specific value on, for example, the main partner, which is a noupdate record. For users with a previous version already installed, this data update will never be executed! You can work around this by using the function
element to temporarily unset the record to noupdate, as follows:
<function name="write" model="ir.model.data"> <function name="search" model="ir.model.data"> <value eval="[('module', '=', 'base'), ('name', '=', 'main_partner')]" /> </function> <value eval="{'noupdate': False}" /> </function> <record id="base.main_partner" model="res.partner"> <field name="book_ids" eval="[(4, ref('book_cookbook'))]" </record> <function name="write" model="ir.model.data"> <function name="search" model="ir.model.data"> <value eval="[('module', '=', 'base'), ('name', '=', 'main_partner')]" /> </function> <value eval="{'noupdate': True}" /> </function>
With this code, you can circumvent any noupdate flag, but be sure this is really what you want. Another option for solving the scenario sketched here is to write a migration script, as outlined in the following recipe.
Odoo also uses XML IDs to keep track of which data is to be deleted after an addon update. If a record had an XML ID from the module's namespace before the update, but the XML ID is not reinstated during the update, the record and its XML ID will be deleted from the database because they're considered obsolete. For a deeper discussion of this mechanism, see the following recipe: Addon updates and data migration.
13.59.141.241