Skip to content

All Odoo ir.actions Types Explained: Window, Server, Client, URL, and Report

DeployMonkey Team · March 23, 2026 13 min read

The ir.actions System

Every click in Odoo's interface triggers an action. When you click a menu item, a button, or a link, Odoo resolves an ir.actions record that tells the web client what to do: open a view, run server code, generate a report, or navigate to a URL. Understanding actions is key to building any Odoo interface.

ir.actions.act_window

The most common action type. It opens a view (or set of views) for a model:

<record id="action_support_tickets" model="ir.actions.act_window">
  <field name="name">Support Tickets</field>
  <field name="res_model">support.ticket</field>
  <field name="view_mode">list,form,kanban,pivot,graph</field>
  <field name="domain">[('active', '=', True)]</field>
  <field name="context">{
    'default_priority': '1',
    'search_default_filter_my': 1,
  }</field>
  <field name="search_view_id" ref="view_ticket_search"/>
  <field name="help" type="html">
    <p class="o_view_nocontent_smiling_face">
      Create your first support ticket
    </p>
  </field>
</record>

Key Attributes

  • res_model: the model to display
  • view_mode: comma-separated list of view types (list, form, kanban, pivot, graph, calendar, activity)
  • domain: default filter applied to all views
  • context: default values and search defaults
  • target: current (default, replaces content), new (dialog/modal), inline (embedded), fullscreen
  • res_id: open a specific record directly in form view

Opening a Specific Form

<record id="action_ticket_form" model="ir.actions.act_window">
  <field name="name">Ticket Details</field>
  <field name="res_model">support.ticket</field>
  <field name="view_mode">form</field>
  <field name="res_id" eval="ref('demo_ticket_1')"/>
</record>

Opening as a Dialog

<record id="action_ticket_wizard" model="ir.actions.act_window">
  <field name="name">Assign Ticket</field>
  <field name="res_model">ticket.assign.wizard</field>
  <field name="view_mode">form</field>
  <field name="target">new</field>
</record>

Returning from Python

def action_open_related(self):
    return {
        'type': 'ir.actions.act_window',
        'name': 'Related Records',
        'res_model': 'related.model',
        'view_mode': 'list,form',
        'domain': [('ticket_id', '=', self.id)],
        'context': {'default_ticket_id': self.id},
    }

ir.actions.server

Server actions execute Python code, send emails, create records, or chain multiple actions. They are the backbone of Odoo's automation system:

<record id="action_send_reminder" model="ir.actions.server">
  <field name="name">Send Reminder Email</field>
  <field name="model_id" ref="model_support_ticket"/>
  <field name="state">code</field>
  <field name="code">
for record in records:
    if record.state == 'new' and record.user_id:
        record.message_post(
            body='Reminder: This ticket needs attention.',
            partner_ids=[record.user_id.partner_id.id])
  </field>
</record>

Server Action States

  • code: execute Python code (with records, env, model variables available)
  • object_create: create a new record
  • object_write: update the current record
  • multi: run multiple child actions in sequence
  • email: send an email using a template
  • followers: subscribe followers to the record
  • next_activity: schedule a next activity

ir.actions.client

Client actions trigger JavaScript on the frontend without a server round-trip:

<record id="action_dashboard" model="ir.actions.client">
  <field name="name">Support Dashboard</field>
  <field name="tag">support_dashboard</field>
  <field name="params">{'show_graph': true}</field>
</record>

The tag maps to a JavaScript action registered on the frontend. Built-in client actions include display_notification and reload:

# Show a notification
def action_notify(self):
    return {
        'type': 'ir.actions.client',
        'tag': 'display_notification',
        'params': {
            'title': 'Success',
            'message': 'Operation completed.',
            'type': 'success',
            'sticky': False,
        },
    }

# Reload the page
def action_reload(self):
    return {
        'type': 'ir.actions.client',
        'tag': 'reload',
    }

ir.actions.act_url

Open a URL in the browser:

def action_open_website(self):
    return {
        'type': 'ir.actions.act_url',
        'url': 'https://www.example.com',
        'target': 'new',  # 'new' = new tab, 'self' = same tab
    }

# Dynamic URL
def action_open_map(self):
    return {
        'type': 'ir.actions.act_url',
        'url': f'https://maps.google.com/?q={self.address}',
        'target': 'new',
    }

ir.actions.report

Generate and download PDF/HTML reports:

<record id="action_report_ticket" model="ir.actions.report">
  <field name="name">Ticket Report</field>
  <field name="model">support.ticket</field>
  <field name="report_type">qweb-pdf</field>
  <field name="report_name">my_module.report_ticket</field>
  <field name="report_file">my_module.report_ticket</field>
  <field name="print_report_name">'Ticket_%s' % object.name</field>
  <field name="binding_model_id" ref="model_support_ticket"/>
  <field name="binding_type">report</field>
</record>

The binding_model_id adds the report to the Print menu on the model's form view. report_type can be qweb-pdf or qweb-html.

Returning from Python Methods

# Return an action from a button click
def action_do_something(self):
    # ... perform logic ...

    # Return an action dict to navigate
    return {
        'type': 'ir.actions.act_window',
        'res_model': 'result.model',
        'view_mode': 'form',
        'res_id': result.id,
        'target': 'current',
    }

    # Or return nothing to stay on current view
    # (implicit return None)

Chaining Actions

Use multi-type server actions to chain multiple actions:

<record id="action_chain" model="ir.actions.server">
  <field name="name">Process and Notify</field>
  <field name="model_id" ref="model_support_ticket"/>
  <field name="state">multi</field>
  <field name="child_ids" eval="[
    (4, ref('action_process')),
    (4, ref('action_send_email')),
  ]"/>
</record>