How it works...

At the low level, the user interface is defined by records stored in special Models. The first two steps create an empty XML file to define the records to be loaded and then add them to the module's list of data files to be installed.

Data files can be anywhere inside the module directory, but the convention is for the user interface to be defined inside a views/ subdirectory using file names after the Model the interface is for. In our case, the library.book interface is in the views/library_book.xml file.

The next step is to define a Window Action to display the user interface in the main area of the web client. The Action has a target Model defined by res_model and sets the title to display to the user using name. These are just the basic attributes. It supports additional attributes, giving much more control on how the Views are rendered, such as what Views are to be displayed, adding filters on the records available, or setting default values. These are discussed in detail in Chapter 10, Backend Views.

In general, data records are defined using a <record> tag, but in our example, the Window Action was defined using the <act_window> tag. This is a shortcut to create records for the ir.actions.act_window Model, where Window Actions are stored.

Similarly, menu items are stored in the ir.ui.menu Model, but a convenience <menuitem> shortcut tag is available and was used.

These are the menu item's main attributes used here:

  • name: This is the menu item text to be displayed.
  • action: This is the identifier of the action to be executed. We use the ID of the Window Action created in the previous step.
  • sequence: This is used to set the order at which the menu items of the same level are presented.
  • parent: This is the identifier for the parent menu item. Our example menu item had no parent, meaning that it is to be displayed at the top of the menu.

At this point, our module can display a menu item, and clicking on it opens Views for the Library Books model. Since nothing specific is set on the Window Action, the default is to display a List (or Tree) view and a form view.

We haven't defined any of these views, so Odoo will automatically create them on the fly. However, we will surely want to control how our views look, so in the next two steps, a form and a tree view are created.

Both views are defined with a record on the ir.ui.view model. The attributes we used are as follows:

  • name: This is a title identifying this view. It is frequent to see the XML ID repeated here, but it can perfectly be a more human readable title.

If the name field is omitted, Odoo will generate one using the model name and the type of view. This is perfectly fine for the standard view of a new model. It is recommended to have a more explicit name when you are extending a view, as this will make your life easier when you are looking for a specific view in the user interface of Odoo.

  • model: This is the internal identifier of the target model, as defined in its
    _name attribute.
  • arch: This is the view architecture, where its structure is actually defined. This is where different types of views differ from each other.

Form views are defined with a top <form> element, and its canvas is a two-column grid. Inside the form, <group> elements are used to vertically compose fields. Two groups result in two columns with fields, which are added using the <field> element. Fields use a default widget according to their data type, but a specific widget can be used with the help of the widget attribute.

Tree views are simpler; they are defined with a top <tree> element containing <field> elements for the columns to be displayed.

Finally, we added a Search view to expand the search option in the box at the top-right. Inside the <search> top-level tag, we can have the ;<field> and <filter> elements. Field elements are additional fields that can be searched from the box. Filter elements are predefined filter conditions that can be activated with a click.