Skip to content

Complete Kanban View Development in Odoo: Cards, Columns, and Drag-Drop

DeployMonkey Team · March 23, 2026 13 min read

Kanban Views in Odoo

The kanban view is one of Odoo's most versatile interfaces. It displays records as cards organized in columns (groups), supports drag-and-drop between columns, and can be customized extensively with QWeb templates. CRM pipelines, project tasks, and inventory operations all use kanban views.

Basic Kanban View Definition

A minimal kanban view requires a QWeb template inside the <kanban> tag:

<record id="view_maintenance_kanban" model="ir.ui.view">
  <field name="name">maintenance.request.kanban</field>
  <field name="model">maintenance.request</field>
  <field name="arch" type="xml">
    <kanban default_group_by="state"
            default_order="priority desc, create_date desc"
            class="o_kanban_small_column">
      <field name="name"/>
      <field name="state"/>
      <field name="priority"/>
      <field name="user_id"/>
      <field name="color"/>
      <templates>
        <t t-name="card">
          <field name="name" class="fw-bold"/>
          <field name="user_id" widget="many2one_avatar_user"/>
          <field name="priority" widget="priority"/>
        </t>
      </templates>
    </kanban>
  </field>
</record>

Declare fields you need at the top of the kanban tag. The t-name="card" template defines each card's content using Odoo 17+ simplified kanban syntax.

Kanban Card Template (Legacy QWeb)

For more control, use the traditional QWeb approach with t-name="kanban-box":

<templates>
  <t t-name="kanban-box">
    <div t-attf-class="oe_kanban_card oe_kanban_global_click
                        o_kanban_record_has_image_fill
                        #{kanban_color(record.color.raw_value)}">
      <div class="oe_kanban_content">
        <div class="o_kanban_record_top">
          <div class="o_kanban_record_headings">
            <strong class="o_kanban_record_title">
              <field name="name"/>
            </strong>
            <span class="o_kanban_record_subtitle text-muted">
              <field name="partner_id"/>
            </span>
          </div>
          <div class="o_kanban_record_top_right">
            <field name="priority" widget="priority"/>
          </div>
        </div>
        <div class="o_kanban_record_body">
          <field name="tag_ids" widget="many2many_tags"
                 options="{'color_field': 'color'}"/>
        </div>
        <div class="o_kanban_record_bottom">
          <div class="oe_kanban_bottom_left">
            <field name="activity_ids" widget="kanban_activity"/>
          </div>
          <div class="oe_kanban_bottom_right">
            <field name="user_id" widget="many2one_avatar_user"/>
          </div>
        </div>
      </div>
    </div>
  </t>
</templates>

Grouped Columns

Kanban views group records into columns. The default_group_by attribute sets the initial grouping:

<kanban default_group_by="stage_id">

For Selection fields, each value becomes a column. For Many2one fields (like stage_id), each related record becomes a column. Users can drag cards between columns, which updates the grouped field automatically.

Column Progress Bars

Add progress bars to column headers showing record distribution:

<kanban default_group_by="stage_id">
  <progressbar field="activity_state"
              colors='{"planned": "success",
                       "today": "warning",
                       "overdue": "danger"}'
              sum_field="expected_revenue"/>
  <!-- templates -->
</kanban>

The sum_field shows the total of a numeric field in the column header. Colors map field values to Bootstrap color classes.

Kanban Buttons and Actions

Add action buttons to cards:

<div class="o_kanban_record_bottom">
  <div class="oe_kanban_bottom_left">
    <a type="object" name="action_approve"
       class="btn btn-sm btn-primary"
       t-if="record.state.raw_value == 'submitted'">
      Approve
    </a>
  </div>
</div>

Use type="object" to call a Python method, or type="action" to trigger an ir.actions. The t-if directive controls visibility based on record state.

Color Coding

Cards can be color-coded using the color integer field:

<field name="color"/>
<!-- In template: -->
<div t-attf-class="oe_kanban_card #{kanban_color(record.color.raw_value)}">

The kanban_color() function maps integers 0-11 to CSS classes. Add a color picker dropdown with the kanban menu:

<div class="o_dropdown_kanban dropdown">
  <a class="dropdown-toggle o-no-caret btn"
     data-bs-toggle="dropdown" href="#">
    <span class="fa fa-ellipsis-v"/>
  </a>
  <div class="dropdown-menu" role="menu">
    <a role="menuitem" type="edit" class="dropdown-item">Edit</a>
    <a role="menuitem" type="delete" class="dropdown-item">Delete</a>
    <ul class="oe_kanban_colorpicker" data-field="color"/>
  </div>
</div>

Restricting Column Creation and Deletion

Control whether users can create or delete columns:

<kanban default_group_by="stage_id"
        group_create="true"
        group_delete="false"
        group_edit="false"
        quick_create="true">

Quick Create

Quick create lets users add records directly from the kanban column header. Define which fields appear in the quick create form:

<kanban quick_create_view="module.quick_create_form_view">

Reference a minimal form view that contains only the essential fields for quick record creation.

Kanban with Images

Display images in cards using the kanban_image function:

<img t-att-src="kanban_image('res.partner',
     'avatar_128', record.partner_id.raw_value)"
     class="o_kanban_image rounded-circle"
     width="40" height="40"/>

Performance Tips

  • Declare only the fields you use in the template to minimize data fetching
  • Avoid computed fields that trigger complex queries in kanban views
  • Use o_kanban_small_column class for narrow columns when showing many groups
  • Limit default records per column with search defaults or domain filters