The most obvious way to make a new feature available to the users is by using a menu item. When you click on a menu item, something happens. This recipe walks you through how to define that something.
We will create a top level menu displaying a sub menu in the left hand menu bar, opening a list of all the customers.
This can also be done using the web user interface, via the settings menu, but we prefer to use XML data files since this is what we'll have to use when creating our addon modules.
In an XML data file of our addon module, perform the following steps:
<act_window id="action_all_customers" name="All customers" res_model="res.partner" view_mode="tree,form" domain="[('customer', '=', True)]" context="{'default_customer': True}" limit="80" />
<menuitem id="menu_custom_toplevel" name="My custom menu" /> <menuitem id="menu_custom_left" parent="menu_custom_toplevel" name="This will appear in the left bar" />
<menuitem id="menu_all_customers" parent="menu_custom_left" action="action_all_customers" sequence="10" groups="" />
If we now upgrade the module, we will see a top level menu that opens a sub menu in the left menu bar. Clicking on that menu item will open a list of all the customers.
The first XML element, act_window
, declares a window action to display a list view with all the customers. We used the most important attributes:
name
: To be used as the title for the views opened by the action.res_model
: This is the model to be used. We are using res.partner
, where Odoo stores all the partners and addresses, including customers.view_mode
: This lists the view types to make available. The default value is tree, view, making available the list and form views. Other possible choices are kanban, graph, calendar, and gantt, explained later in this chapter.domain
: This is optional and allows you to set a filter on the records to be made available in the views. In this case, we want to limit the partners to only those that are customers. We will explain this in more detail in a dedicated recipe later.context
: This can set values made available to the opened views, affecting their behavior. In our example, on new records we want the customer flag's default value to be True
. This will be covered in more depth in another recipe.limit
: This sets the default amount of records that can be seen on list views. It defaults to 80
.Next we create the menu item hierarchy; from the top level menu to the clickable end menu item. The most important attributes for the menuitem
element are:
name
: This is used as the text the menu items display. If your menu item links to an action you can leave this out, because in that case the action's name will be used.parent
(parent_id
if using the record
element): This is the XML ID referencing the parent menu item. Items with no parent are top level menus.action
: This is the XML ID referencing the action to be called. Only menu items without child elements are clickable, so this option is only effective in those cases.sequence
: This is used to order sibling menu items.groups
(groups_id
with the record
tag): This is an optional list of user groups that can access this menu item. If empty, it will be available to all the users.Window actions automatically determine the view to be used by looking up views for the target model, with the intended type (form
, tree
, and so on) and picking the one with the lowest sequence number.
act_window
and menuitem
are convenient shortcut XML tags that hide what you're actually doing: You create a record of the models ir.actions.act_window
and ir.ui.menu
respectively.
To build the menu, the web client reads all the records from ir.ui.menu
and infers their hierarchy from the parent_id
field. Menus are also filtered based on user permissions to models and groups assigned to menus and actions. When a user clicks a menu item, its action
is executed.
Window actions also support a target
attribute to specify how the view is to be presented. Possible choices are:
The window action's view_type
attribute is mostly obsolete by now. The alternative to the default form is tree, which causes the groups lists to render a hierarchical tree. Don't confuse this attribute with the view_mode
attribute used and explained earlier, which actually decides which types of views are used.
There are also some additional attributes available for window actions that are not supported by the act_window
shortcut tag. So to use them, we must use the record
element with the following fields:
Keep in mind that the menu bar at the top and the menu to the left are all made up of the same stuff, the menu items. The only difference is that the items in the top bar don't have any parent menus, while the ones on the left bar have the respective menu item from the top bar as parent. In the left bar, the hierarchical structure is more obvious.
Also bear in mind that for design reasons, the first level menus in the left bar are rendered as a kind of header and standard Odoo doesn't assign an action to them very often. So even if you technically can assign an action to them, your users won't be used to click them and will probably be confused if you expect them to do so.
You'll find a more detailed discussion of the XML ID reference mechanism in Chapter 9, Module Data. For now, just keep in mind that you can set references this way and – very importantly – that order matters. If the tags above were inverted, the addon containing this XML code wouldn't install because menuitem
would refer to an unknown action
.
This can become a pitfall when you add new data files and new elements during your development process, because then the order in which you add those files and elements does not necessarily reflect the order they will be loaded in an empty database. Always check before deployment if your addon installs in an empty database.
The action type ir.actions.act_window
is the most common one, but a menu can refer to any type of action. Technically, it is just the same if you link to a client action, a server action, or any other model defined in the ir.actions.* namespace. It just differs in what the backend makes out of the action.
If you need just a tiny bit more flexibility in the concrete action to be called, look into the server actions that return a window action in turn. If you need complete flexibility on what you present, look into the client actions (ir.actions.client) which allow you to have a completely custom user interface. But only do so as last resort as you lose a lot of Odoo's convenient helpers when using them.
3.147.85.183