View Records

Views are what define how records should be displayed to end-users. They are specified in XML which means that they can be edited independently from the models that they represent. They are flexible and allow a high level of customization of the screens that they control. There exist various types of views. Each of them represents a mode of visualization: form, list, kanban, etc.

Generic structure

Basic views generally share the common structure defined below. Placeholders are denoted in all caps.

<record id="ADDON.MODEL_view_TYPE" model="ir.ui.view">
  <field name="name">NAME</field>
  <field name="model">MODEL</field>
  <!--
  <field name="groups_id" eval="GROUPS"/>
  <field name="priority">PRIORITY</field>
  -->
  <!--
  <field name="inherit_id" ref="REFERENCE"/>
  <field name="mode">PRIMARY</field>
  -->
  <field name="arch" type="xml">
    <VIEW_TYPE>
      <views/>
    </VIEW_TYPE>
  </field>
</record>

View types

  • Form -> display and edit the data from a single record

  • List -> view and edit multiple records

  • Search -> apply filters and perform searches (the result are displayed in the current view list, kanban…)

  • Kanban -> displays records as “cards” configurable as a small template

  • Qweb -> templating of reporting, website…

  • Graph -> visualize aggregations over a number of records or record groups

  • Pivot -> display aggregations as a pivot table

  • Calendar -> display records as events in a daily, weekly, monthly or yearly calendar

Enterprise feature
  • Cohort -> display and understand the way some data changes over a period of time

  • Gantt -> display records as a Gantt charts (for scheduling)

  • Grid -> display computed information in numerical cells are hardly configurable

  • Map -> display records on a map and the routes between them

Fields

View objects expose a number of fields. They are optional unless specified otherwise.

name

Char

Only useful as a mnemonic/description of the view when looking for one in a list of some sort. Most Odoo view names start with the name of the addon and end with the type of view being discussed.

model

Char (mandatory)

The model linked to the view, if applicable.

arch

Text

The description of the view layout depending on view type

groups_id

Many2many -> Groups

The groups allowed to use/access the current view.

If the view extends an existing view, the extension will only be applied for a given user if the user has access to the provided groups_id.

priority

Integer

When a view is requested by model and type, the view matching the model and the type, with the lowest priority will be returned (it is the default view).

It also defines the order of views application during view inheritance. When a view is requested by id, if its mode is not primary its closest parent with mode primary is matched.

inherit_id

Many2one

Reference to the parent view on which the inheritance will be applied. It value is uset by default. Specify the parent using the ref attribute as ref="ADDON.MODEL_parent_view_TYPE". The addon name (separate by dot) is not necessary if the inheritance is done on a record of the same module.

See inheritance information

mode

Selection: extension / primary

Only applies if this view inherits from an other one (inherit_id is not False/Null).

extension (default)

if this view is requested the closest primary view is looked up (via inherit_id), then all views inheriting from it with this view’s model are applied

primary

the closest primary view is fully resolved (even if it uses a different model than this one), then this view’s inheritance specs (<xpath/>) are applied, and the result is used as if it were this view’s actual arch.

An example of where you would want to override mode while using inherit_id is delegation inheritance. In that case your derived model will be separate from its parent and views matching with one won’t match with the other. Suppose you inherit from a view associated with the parent model and want to customize the derived view to show data from the derived model. The mode of the derived view needs to be set to primary, because it’s the base (and maybe only) view for that derived model. Otherwise the view matching rules won’t apply.

See inheritance information

Note

The current context and user access rights may also impact the view abilities.

Inheritance

Inheritance allows you to customize delivered views. This makes it possible, for example, to add content according to the modules installed, or to deliver different displays according to the action.

Inherit views generally share the common structure defined below. Placeholders are denoted in all caps. This synthetic view will update a node targeted by an xpath, and an other targeted by his name and attributes.

The two following view fields inherit_id and mode are used to specify inherited views.

<record id="ADDON.MODEL_view_TYPE" model="ir.ui.view">
  <field name="model">MODEL</field>
  <field name="inherit_id" ref="VIEW_REFERENCE"/>
  <!--
  <field name="mode">PRIMARY</field>
  -->
  <field name="arch" type="xml">
    <xpath expr="XPATH" position="inside">
      CONTENT
    </xpath>
    <NODE ATTRIBUTES="VALUES" position="replace">
      <CONTENT/>
    </NODE>
  </field>
</record>

View resolution

Resolution generates the final arch for a requested/matched primary view:

  1. if the view has a parent, the parent is fully resolved then the current view’s inheritance specs are applied

  2. if the view has no parent, its arch is used as-is

  3. the current view’s children with mode extension are looked up and their inheritance specs are applied depth-first (a child view is applied, then its children, then its siblings)

The inheritance is applied according to inherit_id. If several view record inherit the same view, the order is determined by the priority.

The result of applying children views yields the final arch

Inheritance specs

Inheritance specs are comprised of an element locator, to match the inherited element in the parent view, and children element that will be used to modify the inherited element.

There are three types of element locators for matching a target element:

  • An xpath element with an expr attribute. expr is an XPath expression1 applied to the current arch, the first node it finds is the match

  • a field element with a name attribute, matches the first field with the same name. All other attributes are ignored during matching

  • any other element: the first element with the same name and identical attributes (ignoring position and version attributes) is matched

<xpath expr="page[@name='pg']/group[@name='gp']/field" position="inside">
  <field name="description"/>
</xpath>

<div name="name" position="replace">
  <field name="name2"/>
</div>

The view’s specs are applied sequentially.

1

an extension function is added for simpler matching in QWeb views: hasclass(*classes) matches if the context node has all the specified classes

Inheritance position

The inheritance spec may have an optional position attribute specifying how the matched node should be altered. By default the value is inside.

inside

the content of the inheritance spec is appended to the matched node

<notebook position="inside">
    <page string="New feature">
        ...
    </page>
</notebook>
after

the content of the inheritance spec is added to the matched node’s parent, after the matched node

<xpath expr="//field[@name='x_field']" position="after">
    <field name="x_other_field"/>
</xpath>
before

the content of the inheritance spec is added to the matched node’s parent, before the matched node

<field name=x_field" position="before">
    <field name="x_other_field"/>
</field>
replace

the content of the inheritance spec replaces the matched node. Any text node containing only $0 within the contents of the spec will be replaced by a complete copy of the matched node, effectively wrapping the matched node.

<xpath expr="//field[@name='x_field']" position="replace">
    <div class="wrapper">
        $0
    </div>
</xpath>
attributes

the content of the inheritance spec should be attribute elements with a name attribute and an optional body:

  • if the attribute element has a body, a new attributed named after its name is created on the matched node with the attribute element’s text as value

  • if the attribute element has no body, the attribute named after its name is removed from the matched node. If no such attribute exists, an error is raised

  • if the attribute element has an add attribute, a remove attribute, or both, the value of the matched node’s attribute named after name is recomputed to include the value(s) of add (separated by separator) and delete the value(s) of remove (separated by separator). If separator is not provided, , is used instead.

<field name="x_field" position="attributes">
    <attribute name="invisible">True</attribute>
    <attribute name="class" add="mt-1 mb-1" remove="mt-2 mb-2" separator=" "/>
</field>
move

can be used as a direct child of a inheritance spec with a inside, replace, after or before position attribute to move a node.

<xpath expr="//@target" position="after">
    <xpath expr="//@node" position="move"/>
</xpath>

<field name="target_field" position="after">
    <field name="my_field" position="move"/>
</field>

Model Commons

Model.get_views(views, options=None)[source]

Returns the fields_views of given views, along with the fields of the current model, and optionally its filters for the given action.

The return of the method can only depend on the requested view types, access rights (views or other records), view access rules, options, context lang and TYPE_view_ref (other context values cannot be used).

Python expressions contained in views or representing domains (on python fields) will be evaluated by the client with all the context values as well as the record values it has.

Parameters
  • views – list of [view_id, view_type]

  • options (dict) –

    a dict optional boolean flags, set to enable:

    toolbar

    includes contextual actions when loading fields_views

    load_filters

    returns the model’s filters

    action_id

    id of the action to get the filters, otherwise loads the global filters or the model

Returns

dictionary with fields_views, fields and optionally filters

Model.get_view([view_id | view_type='form'])[source]

Get the detailed composition of the requested view like model, view architecture.

The return of the method can only depend on the requested view types, access rights (views or other records), view access rules, options, context lang and TYPE_view_ref (other context values cannot be used).

Parameters
  • view_id (int) – id of the view or None

  • view_type (str) – type of the view to return if view_id is None (‘form’, ‘tree’, …)

  • options (dict) – boolean options to return additional features: - bool mobile: true if the web client is currently using the responsive mobile view (to use kanban views instead of list views for x2many fields)

Returns

composition of the requested view (including inherited views and extensions)

Return type

dict

Raises
  • AttributeError

    • if the inherited view has unknown position to work with other than ‘before’, ‘after’, ‘inside’, ‘replace’

    • if some tag other than ‘position’ is found in parent view

  • Invalid ArchitectureError – if there is view type other than form, tree, calendar, search etc… defined on the structure