Unlike views, regular data records don't have an XML arch
structure and can't be extended using XPath expressions. But they can still be modified replacing the values in their fields.
The <record id="x" model="y">
data loading elements actually perform an insert
or update
operation on the model y
: if model x
does not exist, it is created; otherwise, it is updated/written over.
Since records in other modules can be accessed using a <model>.<identifier>
global identifier, it's possible for our module to overwrite something that was written before by another module.
As an example, let's change the menu option created by the todo_app
module to My To-Do
. For this, we can add the following to the todo_user/views/todo_task.xml
file:
<!-- Modify menu item --> <record id="todo_app.menu_todo_task" model="ir.ui.menu"> <field name="name">My To-Do</field> </record>
We can also modify the action used in the menu item. Actions have an optional context attribute. It can provide default values for view fields and filters. We will use it to have enabled by default the My Tasks filter, defined earlier in this chapter:
<!-- Action to open To-Do Task list --> <record model="ir.actions.act_window" id="todo_app.action_todo_task"> <field name="context"> {'search_default_filter_my_tasks': True} </field> </record>
The To-Do application included a record rule to ensure that each task would only be visible to the user that created it. But now, with the addition of social features, we need the task followers to also access them. The social network module does not handle this by itself.
Also, now tasks can have users assigned to them, so it makes more sense to have the access rules to work on the responsible user instead of the user who created the task.
The plan would be the same as we did for the menu item: overwrite todo_app.todo_task_user_rule
to modify the domain_force
field to a new value.
The convention is to keep security-related files in a security
subdirectory, so we will create a security/todo_access_rules.xml
file with the following content:
<?xml version="1.0" encoding="utf-8"?> <odoo> <data noupdate="1"> <record id="todo_app.todo_task_per_user_rule" model="ir.rule"> <field name="name">ToDo Tasks for owner and followers</field> <field name="model_id" ref="model_todo_task"/> <field name="groups" eval="[(4, ref('base.group_user'))]"/> <field name="domain_force"> ['|',('user_id','in', [user.id,False]), ('message_follower_ids','in', [user.partner_id.id])] </field> </record> </data> </odoo>
This overwrites the todo_task_per_user_rule
record rule from the todo_app
module. The new domain filter now makes a task visible to the responsible user, user_id
, or to everyone if the responsible user is not set (equals False
); it is visible to all the task followers as well.
The record rule runs in a context where a user
variable is available and represents the record for the current session user. Since Followers are partners, not users
, instead of user.id
, we need to use user.partner_id
.
The groups field is a to-many relation. Editing data in these fields uses a special notation. The code 4
used here is to append to the list of related records. Also used often is code 6
, to instead completely replace the related records with a new list. We well discuss this notation in more detail in Chapter 4, Module Data.
The noupdate="1"
attribute of the record element means that this record data will only be written on installation actions and will be ignored on module upgrades. This allows for it to be customization, without taking those risk of overwriting customizations and losing them when doing an module upgrade sometime in the future.
As usual, we must not forget to add the new file to data attribute in the the __manifest__.py
:
'data': ['views/todo_task.xml', 'security/todo_access_rules.xml'],