Finally some UI part in odoo development
Now that we’ve created our new model and its corresponding access rights, it is time to interact with the user interface.
Data Files (XML)
Reference: the documentation related to this topic can be found in Data Files.
In Chapter 5: Security - A Brief Introduction, we added data through a CSV file. The CSV format is convenient when the data to load has a simple format. When the format is more complex (e.g. load the structure of a view or an email template), we use the XML format. For example, this help field contains HTML tags. While it would be possible to load such data through a CSV file, it is more convenient to use an XML file.
The XML files must be added to the same folders as the CSV files and defined similarly in the __manifest__.py. The content of the data files is also sequentially loaded when a module is installed or updated, therefore all remarks made for CSV files hold true for XML files. When the data is linked to views, we add them to the views folder.
In this chapter we will load our first action and menus though an XML file. Actions and menus are standard records in the database.
In Odoo, the user interface (actions, menus and views) is largely defined by creating and composing records defined in an XML file. A common pattern is Menu > Action > View. To access records the user navigates through several menu levels; the deepest level is an action which triggers the opening of a list of the records.
Actions
Actions can be triggered in three ways:
-
by clicking on menu items (linked to specific actions)
-
by clicking on buttons in views (if these are connected to actions)
-
as contextual actions on object
We will only cover the first case in this chapter. The second case will be covered in a later chapter while the last is the focus of an advanced topic. In our Real Estate example, we would like to link a menu to the estate.property model, so we are able to create a new record. The action can be viewed as the link between the menu and the model.
A basic action for our test_model is:
<record id="test_model_action" model="ir.actions.act_window">
<field name="name">Test action</field>
<field name="res_model">test_model</field>
<field name="view_mode">tree,form</field>
</record>
-
idis an external identifier. It can be used to refer to the record (without knowing its in-database identifier). -
modelhas a fixed value ofir.actions.act_window(Window Actions (ir.actions.act_window)). -
nameis the name of the action. -
res_modelis the model which the action applies to. -
view_modeare the views that will be available; in this case they are the list (tree) and form views. We’ll see later that there can be other view modes.
Menu
To reduce the complexity in declaring a menu (ir.ui.menu) and connecting it to the corresponding action, we can use the <menuitem> shortcut .
A basic menu for our test_model_action is:
<menuitem id="test_model_menu_action" action="test_model_action"/>
The menu test_model_menu_action is linked to the action test_model_action, and the action is linked to the model test_model. As previously mentioned, the action can be seen as the link between the menu and the model.
However, menus always follow an architecture, and in practice there are three levels of menus:
-
The root menu, which is displayed in the App switcher (the Odoo Community App switcher is a dropdown menu)
-
The first level menu, displayed in the top bar
-
The action menus
The easiest way to define the structure is to create it in the XML file. A basic structure for our test_model_action is:
<menuitem id="test_menu_root" name="Test">
<menuitem id="test_first_level_menu" name="First Level">
<menuitem id="test_model_menu_action" action="test_model_action"/>
</menuitem>
</menuitem>
Fields, Attributes And View
Default Values
Any field can be given a default value. In the field definition, add the option default=X where X is either a Python literal value (boolean, integer, float, string) or a function taking a model and returning a value:
name = fields.Char(default="Unknown")
last_seen = fields.Datetime("Last Seen", default=fields.Datetime.now)
The name field will have the value ‘Unknown’ by default while the last_seen field will be set as the current time.