Skip to content

Actions

Window Actions

Basic Window Action

xml
<record id="action_model_list" model="ir.actions.act_window">
    <field name="name">Model Records</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form</field>
    <field name="target">current</field>
    <field name="help" type="html">
        <p class="o_view_nocontent_smiling_face">
            Create your first record!
        </p>
    </field>
</record>

Window Action with Domain and Context

xml
<record id="action_filtered_records" model="ir.actions.act_window">
    <field name="name">Active Records</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form</field>
    <field name="domain">[('active', '=', True)]</field>
    <field name="context">{
        'default_active': True,
        'search_default_current_month': 1
    }</field>
    <field name="limit">80</field>
</record>

Form Action for Specific Record

xml
<record id="action_open_record" model="ir.actions.act_window">
    <field name="name">Edit Record</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">form</field>
    <field name="res_id" ref="model_record_id"/>
    <field name="target">new</field>
</record>

Multi-View Window Action

xml
<record id="action_multi_view" model="ir.actions.act_window">
    <field name="name">Multi View Action</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form,kanban,calendar,graph,pivot</field>
    <field name="view_id" ref="view_tree_custom"/>
</record>

<!-- Specify view sequences -->
<record id="action_multi_view_view_tree" model="ir.actions.act_window.view">
    <field name="sequence" eval="1"/>
    <field name="view_mode">tree</field>
    <field name="view_id" ref="view_tree_custom"/>
    <field name="act_window_id" ref="action_multi_view"/>
</record>

<record id="action_multi_view_view_form" model="ir.actions.act_window.view">
    <field name="sequence" eval="2"/>
    <field name="view_mode">form</field>
    <field name="view_id" ref="view_form_custom"/>
    <field name="act_window_id" ref="action_multi_view"/>
</record>

Server Actions

Python Code Server Action

xml
<record id="server_action_python" model="ir.actions.server">
    <field name="name">Process Records</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="binding_model_id" ref="model_model_name"/>
    <field name="state">code</field>
    <field name="code">
for record in records:
    if record.state == 'draft':
        record.write({
            'state': 'confirmed',
            'confirmed_date': fields.Datetime.now(),
            'confirmed_by': env.user.id
        })
        
# Send notification
env['mail.thread'].message_post(
    body="Records have been processed",
    message_type='notification'
)

# Log activity
records.message_post(body="Status updated to confirmed")
    </field>
</record>

Multi-Action Server Action

xml
<record id="server_action_multi" model="ir.actions.server">
    <field name="name">Multi Step Process</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="state">multi</field>
</record>

<record id="server_action_step1" model="ir.actions.server">
    <field name="name">Step 1: Validate</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="state">code</field>
    <field name="sequence">1</field>
    <field name="code">
if not records.filtered(lambda r: r.state == 'draft'):
    raise UserError("No draft records to process")
    </field>
</record>

<record id="server_action_step2" model="ir.actions.server">
    <field name="name">Step 2: Update Records</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="state">code</field>
    <field name="sequence">2</field>
    <field name="code">
records.write({'state': 'processing'})
    </field>
</record>

Object Method Server Action

xml
<record id="server_action_method" model="ir.actions.server">
    <field name="name">Call Method</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="binding_model_id" ref="model_model_name"/>
    <field name="state">object_create</field>
    <field name="crud_model_id" ref="model_other_model"/>
    <field name="link_field_id" ref="field_model_name_other_id"/>
    <field name="fields_lines">
        <record model="ir.server.object.lines">
            <field name="col1" ref="field_other_model_name"/>
            <field name="value">record.name + ' - Copy'</field>
            <field name="type">equation</field>
        </record>
        <record model="ir.server.object.lines">
            <field name="col1" ref="field_other_model_date"/>
            <field name="value">datetime.now()</field>
            <field name="type">equation</field>
        </record>
    </field>
</record>

URL Actions

External URL Action

xml
<record id="action_external_url" model="ir.actions.act_url">
    <field name="name">Open Website</field>
    <field name="url">https://www.example.com</field>
    <field name="target">new</field>
</record>

Dynamic URL Action

xml
<record id="action_dynamic_url" model="ir.actions.act_url">
    <field name="name">Open Record URL</field>
    <field name="url">/web#id={{object.id}}&amp;model={{object._name}}&amp;view_type=form</field>
    <field name="target">self</field>
</record>

Report URL Action

xml
<record id="action_report_url" model="ir.actions.act_url">
    <field name="name">Download Report</field>
    <field name="url">/report/pdf/module.report_template/{{object.id}}</field>
    <field name="target">self</field>
</record>

Report Actions

PDF Report Action

xml
<record id="action_report_pdf" model="ir.actions.report">
    <field name="name">Model Report</field>
    <field name="model">model.name</field>
    <field name="report_type">qweb-pdf</field>
    <field name="report_name">module.report_template</field>
    <field name="report_file">module.report_template</field>
    <field name="binding_model_id" ref="model_model_name"/>
    <field name="binding_type">report</field>
</record>

HTML Report Action

xml
<record id="action_report_html" model="ir.actions.report">
    <field name="name">HTML Report</field>
    <field name="model">model.name</field>
    <field name="report_type">qweb-html</field>
    <field name="report_name">module.report_template_html</field>
    <field name="report_file">module.report_template_html</field>
    <field name="paperformat_id" ref="base.paperformat_euro"/>
</record>

Excel Report Action

xml
<record id="action_report_xlsx" model="ir.actions.report">
    <field name="name">Excel Export</field>
    <field name="model">model.name</field>
    <field name="report_type">xlsx</field>
    <field name="report_name">module.report_excel</field>
    <field name="report_file">module.report_excel</field>
    <field name="binding_model_id" ref="model_model_name"/>
</record>

Wizard Actions

Simple Wizard Action

xml
<record id="action_wizard_simple" model="ir.actions.act_window">
    <field name="name">Simple Wizard</field>
    <field name="res_model">wizard.model</field>
    <field name="view_mode">form</field>
    <field name="target">new</field>
    <field name="binding_model_id" ref="model_model_name"/>
    <field name="binding_type">action</field>
</record>

Multi-Step Wizard Action

xml
<record id="action_wizard_multi_step" model="ir.actions.act_window">
    <field name="name">Multi Step Wizard</field>
    <field name="res_model">wizard.multi.step</field>
    <field name="view_mode">form</field>
    <field name="target">new</field>
    <field name="context">{
        'default_step': 'step1',
        'active_ids': active_ids,
        'active_model': active_model
    }</field>
</record>

Wizard with Custom View

xml
<record id="wizard_view_form" model="ir.ui.view">
    <field name="name">wizard.form</field>
    <field name="model">wizard.model</field>
    <field name="arch" type="xml">
        <form string="Wizard Title">
            <group>
                <field name="field1"/>
                <field name="field2"/>
            </group>
            <footer>
                <button string="Process" name="action_process" 
                        type="object" class="btn-primary"/>
                <button string="Cancel" class="btn-secondary" 
                        special="cancel"/>
            </footer>
        </form>
    </field>
</record>

<record id="action_wizard_custom_view" model="ir.actions.act_window">
    <field name="name">Custom Wizard</field>
    <field name="res_model">wizard.model</field>
    <field name="view_mode">form</field>
    <field name="view_id" ref="wizard_view_form"/>
    <field name="target">new</field>
</record>

Client Actions

JavaScript Client Action

xml
<record id="action_client_js" model="ir.actions.client">
    <field name="name">Custom Dashboard</field>
    <field name="tag">custom_dashboard</field>
    <field name="context">{
        'dashboard_type': 'sales',
        'period': 'monthly'
    }</field>
</record>

Client Action with Parameters

xml
<record id="action_client_params" model="ir.actions.client">
    <field name="name">Interactive Chart</field>
    <field name="tag">interactive_chart</field>
    <field name="params" eval="{'chart_type': 'line', 'data_source': 'sales.report'}"/>
    <field name="context">{'default_period': 'current_year'}</field>
</record>

Cron Actions

Scheduled Action

xml
<record id="cron_daily_cleanup" model="ir.cron">
    <field name="name">Daily Cleanup</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="state">code</field>
    <field name="code">model.cleanup_old_records()</field>
    <field name="interval_number">1</field>
    <field name="interval_type">days</field>
    <field name="nextcall" eval="(DateTime.now() + timedelta(days=1)).strftime('%Y-%m-%d 02:00:00')"/>
    <field name="active" eval="True"/>
</record>

Cron with Method Call

xml
<record id="cron_send_reminders" model="ir.cron">
    <field name="name">Send Daily Reminders</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="state">object_write</field>
    <field name="code">send_daily_reminders()</field>
    <field name="interval_number">1</field>
    <field name="interval_type">days</field>
    <field name="nextcall" eval="(DateTime.now() + timedelta(hours=1)).strftime('%Y-%m-%d %H:00:00')"/>
    <field name="user_id" ref="base.user_admin"/>
    <field name="doall" eval="False"/>
</record>

Action Bindings

Model Binding

xml
<record id="action_with_binding" model="ir.actions.server">
    <field name="name">Quick Action</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="binding_model_id" ref="model_model_name"/>
    <field name="binding_type">action</field>
    <field name="state">code</field>
    <field name="code">
records.write({'processed': True})
    </field>
</record>

Report Binding

xml
<record id="report_with_binding" model="ir.actions.report">
    <field name="name">Custom Report</field>
    <field name="model">model.name</field>
    <field name="report_type">qweb-pdf</field>
    <field name="report_name">module.report_template</field>
    <field name="binding_model_id" ref="model_model_name"/>
    <field name="binding_type">report</field>
</record>

View Binding (Button)

xml
<!-- In view definition -->
<button name="%(action_custom_wizard)d" 
        string="Open Wizard" 
        type="action" 
        class="btn-primary"/>

<button name="action_server_method" 
        string="Server Action" 
        type="object" 
        confirm="Are you sure?"/>

Advanced Action Patterns

Conditional Actions

xml
<record id="action_conditional" model="ir.actions.act_window">
    <field name="name">Conditional View</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form</field>
    <field name="domain">[('state', 'in', ['draft', 'confirmed'])]</field>
    <field name="context">{
        'create': False if context.get('readonly_mode') else True,
        'edit': False if context.get('readonly_mode') else True,
        'delete': False
    }</field>
</record>

Action with Groups

xml
<record id="action_restricted" model="ir.actions.act_window">
    <field name="name">Admin Only Action</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form</field>
    <field name="groups_id" eval="[(4, ref('base.group_system'))]"/>
</record>

Parent-Child Actions

xml
<record id="action_parent_records" model="ir.actions.act_window">
    <field name="name">Parent Records</field>
    <field name="res_model">parent.model</field>
    <field name="view_mode">tree,form</field>
</record>

<record id="action_child_records" model="ir.actions.act_window">
    <field name="name">Child Records</field>
    <field name="res_model">child.model</field>
    <field name="view_mode">tree,form</field>
    <field name="domain">[('parent_id', '=', active_id)]</field>
    <field name="context">{
        'default_parent_id': active_id,
        'search_default_parent_id': active_id
    }</field>
</record>

Top Menu

xml
<menuitem id="menu_main" 
          name="Main Module" 
          sequence="10"/>
xml
<menuitem id="menu_records" 
          name="Records" 
          parent="menu_main" 
          action="action_model_list" 
          sequence="10"/>
xml
<menuitem id="menu_admin" 
          name="Administration" 
          parent="menu_main" 
          action="action_admin_panel"
          groups="base.group_system" 
          sequence="100"/>

Dynamic Menu

xml
<menuitem id="menu_dynamic" 
          name="Dynamic Menu" 
          parent="menu_main" 
          action="action_dynamic_content"
          active="True"
          sequence="20"/>

Security and Permissions

Action with Record Rules

xml
<record id="action_with_rules" model="ir.actions.act_window">
    <field name="name">My Records</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form</field>
    <field name="domain">[('user_id', '=', uid)]</field>
</record>

<!-- Corresponding record rule -->
<record id="rule_own_records" model="ir.rule">
    <field name="name">Own Records Only</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="domain_force">[('user_id', '=', user.id)]</field>
    <field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>

Action Security

xml
<record id="action_secure" model="ir.actions.act_window">
    <field name="name">Secure Action</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form</field>
    <field name="groups_id" eval="[(6, 0, [ref('base.group_user'), ref('custom.group_manager')])]"/>
</record>

Action Context Variables

Common Context Variables

xml
<record id="action_with_context" model="ir.actions.act_window">
    <field name="name">Context Example</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form</field>
    <field name="context">{
        'default_field_name': 'Default Value',
        'search_default_filter_name': 1,
        'group_by': 'category_id',
        'create': True,
        'edit': True,
        'delete': False,
        'duplicate': False,
        'active_test': False,
        'lang': 'en_US',
        'tz': 'UTC',
        'uid': uid,
        'company_id': company_id,
        'allowed_company_ids': [company_id]
    }</field>
</record>

Dynamic Context

xml
<record id="action_dynamic_context" model="ir.actions.act_window">
    <field name="name">Dynamic Context</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form</field>
    <field name="context">{
        'default_date': context_today().strftime('%Y-%m-%d'),
        'default_user_id': uid,
        'search_default_my_records': 1 if context.get('filter_my_records') else 0,
        'tree_view_ref': 'module.view_tree_compact' if context.get('compact_view') else False
    }</field>
</record>

Performance Optimization

Optimized Actions

xml
<record id="action_optimized" model="ir.actions.act_window">
    <field name="name">Optimized List</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form</field>
    <field name="limit">80</field>
    <field name="context">{
        'active_test': True,
        'prefetch_fields': ['name', 'state', 'date']
    }</field>
    <field name="domain">[('active', '=', True)]</field>
</record>

Lazy Loading Actions

xml
<record id="action_lazy_load" model="ir.actions.act_window">
    <field name="name">Lazy Loaded Records</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">tree,form</field>
    <field name="auto_search" eval="False"/>
    <field name="context">{'search_disable_custom_filters': True}</field>
</record>