🎨 DRKDS Studio

A powerful no-code / low-code customisation suite for Odoo 19. Build views, automate workflows, manage models, configure security — all without leaving the browser.

🏗️ View Builders ⚙️ Automation 🗃️ Custom Models 🔐 Security 📦 Module Export 🌐 API Panel
🗂️

All Features at a Glance

📋
Form View Builder
Add, reorder, configure fields. Manage widgets, conditional attrs, action buttons.
☰
List View Builder
Manage columns, row decorations, optional columns, multi-sort.
📌
Kanban View Builder
Drag fields onto the kanban card. Pick status dot, badges, avatars.
🔍
Search View Builder
Add/remove searchable fields. Build groupby and filter options.
📊
Pivot View Builder
Assign Row Group, Column Group, Measure roles with live toggles.
📈
Graph View Builder
Bar, Line, Pie charts. Configure axes and measures visually.
📅
Calendar View Builder
Map start/end dates, color-by field, default mode, quick create.
🗓️
Gantt View Builder
Interactive Frappe Gantt. No library install required.
🖨️
Report Designer
Build printable QWeb reports. Bind to the model's Print menu.
⚙️
Automation Builder
Full inline rule builder — 7 action types, triggers, filters.
🛠️
Server Actions
Create Python server actions, bind to Action menu.
🔗
Outgoing Webhooks
POST JSON payloads to external URLs on model events.
⏰
Scheduled Actions
Create time-based cron jobs with Python code.
🔢
Sequence Builder
Define custom sequences with prefix, suffix, padding.
🗃️
Custom Models
Create entire new data models without any Python code.
🏷️
Fields & Defaults
Add custom fields, set global/user/company default values.
📝
Selection Values Editor
Add or remove values from Selection fields.
🔀
Relations Browser
Explore Many2one, One2many, Many2many links visually.
🔐
Access Rights Manager
Grant CRUD permissions per group on any model.
📜
Record Rules Manager
Row-level security with domain filters and group scoping.
📧
Email Templates
Build reusable email templates using Jinja2 expressions.
🗂️
Menu Builder
Create menus and window actions. Drag to reorder globally.
📦
Module Export
Export all Studio customisations as a portable .zip module.
🌐
API Info Panel
Browse JSON-RPC endpoints. Copy Python/JS/cURL snippets.
💡 Tip: Use the sidebar to jump to any topic. Each section has step-by-step instructions, flow diagrams, and real-world examples.

⚡ Quick Start Guide

Get from zero to a customised view in under 5 minutes.

🎯

Opening Studio

1
Navigate to any Odoo model

Open a form or list view of the model you want to customise (e.g. Sales Orders, Contacts, Employees).

2
Click the 🎨 Studio icon in the top-right systray

The Studio panel slides in from the right. The model technical name (e.g. sale.order) is shown just below the header.

3
Choose a view type

Click one of the toggle buttons: Form · List · Search · Kanban · Pivot · Graph · Cal · Gantt · Rpt

Open Model
→
Click 🎨
→
Pick View Type
→
Edit
→
💾 Save
⚡

Most Common Tasks

1
Studio → Form → Add tab

All fields not yet in the view are listed. Click any to add instantly.

2
Or click "Create New Custom Field"

Opens the Field Wizard. Pick type → fill label → Save. The new field is added to both the model and the view.

3
Click Save in panel footer

Changes are written to the database view XML.

1
Studio → Auto tab

Lists all automation rules for this model.

2
Click "New Automation Rule"

Set: Name, Trigger (When), optional Filters.

3
Click "Add" in Actions, choose type

E.g. "Send Email" → pick template → Save Rule.

Trigger fires
→
Filter check
→
Run actions
1
Studio → Rpt tab

Shows all Studio reports for this model.

2
Click "New Report"

Enter report name, tick the fields to include, click Create.

3
Open record → Print menu

The new report appears in the Print (⎙) dropdown for every record of this model.

1
Studio panel → "Models" button (header)

Opens the Custom Models manager.

2
Click "New Custom Model"

Enter display name (e.g. "Project Phase"). Technical name auto-fills as x_project_phase.

3
Click "Open in Editor"

Navigate to the model's list view, then use Studio to add custom fields and configure views.

📋 Form View Builder

Add, remove, reorder, and configure fields on any form view without writing XML.

FieldsWidgetsConditionsButtons
🗺️

Complete Workflow

Open Studio
→
Form toggle
→
Add / Reorder Fields
→
Set Props
→
💾 Save
📋

Adding Fields

➕

Add Tab — existing or new field

1
Click the "Add" tab in the panel

All fields on this model not yet in the view are shown with a type badge and technical name.

2
Click any field to add it instantly

The field is inserted into the view. Switch to "Fields" tab to see and reorder it.

3
To create a brand-new field → "Create New Custom Field"

Opens the Field Wizard: choose type, label, and type-specific options. The field is created on the model and added to the view in one step.

4
To add an action button → "Add Action Button"

Set: Label, Type (Object/Method or Action/XML-ID), Placement (Header or Sheet body), Style (Primary/Secondary/Warning/Danger).

↕️

Reorder & Remove Fields

1
Click the "Fields" tab

All fields currently in the view are listed with drag handles.

2
Drag the ☰ handle to reorder

"Unsaved changes" badge appears in footer.

3
Click ✕ to remove a Studio-added field

Core model fields show a 🔒 and cannot be removed from the panel.

💡 One2many fields show a list icon — clicking it opens the O2M Column Editor to manage sub-list columns.
⚙️

Field Properties (Props Tab)

PropertyExample valueEffect
Requiredstate == 'draft'Field is mandatory when condition is true
Readonlystate != 'draft'Field is read-only when condition is true
Invisibletype == 'service'Field is hidden when condition is true
WidgetstatusbarChanges how the field renders in the form
✅ Leave any property blank to disable it. Python expressions reference the record's field values directly (no record. prefix needed).
🛠️

Other Panel Tabs

TabWhat you can do
StructManage tabs (notebook pages), smart buttons, field groups, separators, statusbar field, chatter toggle
XMLEdit raw view XML directly — invalid XML is rejected before saving
ModelsCreate or delete entire custom models from the panel header

☰ List View Builder

Add, remove, and reorder columns. Manage list options, row decorations, optional columns, and sorting.

🗺️

Workflow

Studio → List
→
Cols tab
→
Reorder / Remove
→
Add tab → new cols
→
Opts tab → decorations
→
💾 Save
☰

Step 1 — Switch to List Mode

1
Click the Studio icon, then "List" in the view toggle

The Fields tab label changes to "Cols" reflecting column management.

2
Optionally create or switch list views

Click "New / Manage List Views" below the toggle. Enter a name → Create List View, or click the open icon on an existing Studio list view to load it.

↕️

Step 2 — View & Reorder Columns (Cols tab)

1
Click the "Cols" tab

All columns currently in the list are shown. Hint: "Drag to reorder columns. Click to edit column options."

2
Drag the ☰ handle to reorder

"Unsaved changes" badge appears in panel footer.

3
Click ✕ to remove a Studio-added column

Core model columns show a 🔒 and cannot be removed.

4
Click a column row to access per-column settings

Opens inline options for that column (see Column Details below).

➕

Step 3 — Add a Column (Add tab)

1
Click the "Add" tab

Lists all model fields not yet shown as columns.

2
Click a field to add it as a column

The field appears at the end of the column list. Drag-reorder it under "Cols".

3
Click "Create New Custom Field" to create a new field

Opens the Field Wizard to create a new model field which is also added as a column.

🏷️

Column Details (per-column options)

OptionDescription
Optional columnMark as optional → users can show/hide it from the column header menu
col_invisiblePython expression — hides the column when true (e.g. context.get('no_qty'))
AggregateAggregation function for numeric columns shown in list footer: sum, avg, min, max
⚙️

Step 4 — List Options (Opts tab)

The Opts tab is visible only in List mode. It provides list-level configuration.

1
Editable mode

Choose whether the list is editable inline: Top (new row at top), Bottom (new row at bottom), or Not editable.

2
Behaviour toggles

Enable/disable: no_open (row click does not open form), create, delete, import, export_xlsx.

3
Default Group By and Default Order

Set a default grouping field and a default sort field with direction (asc / desc).

4
Row Decorations

Add conditional row highlight rules. Choose a decoration class and enter a Python condition. Click Add Decoration. Existing decorations can be deleted with ✕.

5
Header Buttons

Add custom action buttons to the list header. Set: label, icon, style, and the server action name. Click Add Button.

6
Click "Save List Options"

This is a separate save from the main panel footer Save. Applies list-level config changes.

🎨

Row Decoration Classes

ClassVisualExample condition
decoration-success■ Greenstate == 'done'
decoration-warning■ Amberdate_deadline < today
decoration-danger■ Redstate == 'cancel'
decoration-info■ Bluepriority == '2'
decoration-muted■ Greyactive == False
decoration-bfBoldamount_total > 50000
decoration-itItalicis_draft
⚠️ Use decoration-muted, NOT decoration-secondary — the latter is invalid in Odoo 19.
✅ Decorations use Python expressions evaluated against each record. Example: state == 'cancel' with decoration-danger turns cancelled rows red.

📌 Kanban View Builder

Configure which fields appear on kanban cards and control card appearance — status ribbon, color, groupby, quick create.

Studio → Kanban
→
Create view (if none)
→
Card tab → add/reorder fields
→
Cfg tab → appearance
→
💾 Save
1️⃣

Step 1 — Switch to Kanban Mode

1
Click the Studio icon, then "Kanban" in the view toggle

The Fields tab label changes to "Card".

2
If the model has no kanban view → click "Create Kanban View"

Studio auto-creates a basic kanban view with the title/name field. The card field list then becomes available.

🃏

Step 2 — Manage Card Fields (Card tab)

1
Click the "Card" tab

Lists all fields on each kanban card. Hint: "Drag to reorder fields shown on each kanban card."

2
Drag ☰ to reorder card fields

Updates the XPath //t[@t-name='card'] in the view arch.

3
Click ✕ to remove a Studio-added field

Core fields (🔒) cannot be removed.

4
Click "Add" tab → click a field to add it to the card

The field appears at the end of the card field list.

💡 Click Save in the panel footer to apply card field changes to the view.
⚙️

Step 3 — Configure Card Appearance (Cfg tab)

The Cfg tab appears next to "Add" when a kanban view exists.

1
Status Ribbon

Select a field for the ribbon indicator. priority shows star ratings; kanban_state shows a traffic-light dot. "None" disables the ribbon.

2
Color By

Select an Integer field (values 0–11) for card colour highlighting. Users can then pick a colour from the card's ⋮ menu. "None" disables colour. Requires Integer, not Many2one.

3
Default Group By

Select a many2one or selection field to group the kanban by default on load. "None" = no default grouping.

4
Quick Create toggle

Enabled (default) = clicking an empty column header opens a quick-create input. Disabled = requires opening a full form to create records.

5
Click "Save Kanban Config"

Saves the configuration to the kanban view XML. Button appears only when changes are pending (dirty state).

💡

Tips

  • The Props tab is disabled in Kanban mode — field attributes are not editable per-card from the panel.
  • Use the XML tab to hand-edit the raw kanban view for advanced customisation.
  • Color By requires an Integer field with values 0–11 (Odoo's built-in colour palette). Selection fields do not work for this.

📊 Pivot View Builder

Configure row groups, column groups, measures, date granularity, and view name for the pivot analysis view.

1️⃣

Step 1 — Switch to Pivot Mode

1
Click the Studio icon, then "Pivot" in the view toggle

Hint: "Assign fields as Row groups, Column groups, or Measures."

2
If the model has no pivot view → click "Create Pivot View"

Studio auto-creates a basic pivot view. The field configuration then becomes available.

✏️

Step 2 — Set View Name

The View Name input at the top of the Pivot tab sets the internal name saved with the view. Example: Monthly Revenue Pivot. Editing it marks the view as dirty.

➕

Step 3 — Add Fields

1
Click the "Add" tab or "Add Pivot Field" button

Lists all suitable fields not yet in the pivot view.

2
Click a field to add it

Numeric fields default to Meas role; others default to Row role.

🎯

Step 4 — Set Field Roles

Each pivot field shows three role buttons: Row, Col, Meas.

RoleEligible TypesPurpose
Rowmany2one, selection, date, datetime, charGroups data into rows (vertical axis)
Colmany2one, selection, date, datetimeGroups data into columns (horizontal axis)
Measinteger, float, monetaryNumeric value aggregated in pivot cells
1
Click a role button to assign it

The active role is highlighted. Clicking an already-active role deactivates it (field has no role).

2
Date/Datetime granularity

When a date/datetime field is assigned Row or Col role, a granularity dropdown appears: Day · Week · Month · Quarter · Year.

3
Multiple Meas fields

Multiple Measure fields can be added — each appears as a separate column in the pivot table.

4
Remove a field with ✕
⚠️ If no field has the Meas role, the pivot table will display no data. Studio shows an inline warning when this is detected.
🔄

Example: Sales Analysis

Row: Salesperson
+
Col: Month (Monthly granularity)
+
Meas: Amount Total
→
💾 Save

Result: A matrix with each salesperson on rows, months on columns, showing total amount per cell.

💾

Step 5 — Save or Reset

1
Click "Save" in the panel footer

Writes the view name and all field roles (including date granularity) to the pivot view XML using //pivot position="replace".

2
Click "Reset" to discard changes

Reloads the pivot field list from the server.

📈 Graph View Builder

Configure bar, line, or pie chart views with field roles, view name, and chart type selector.

1️⃣

Step 1 — Switch to Graph Mode

1
Click the Studio icon, then "Graph" in the view toggle

Hint: "Select chart type and assign Row (category) and Measure (value) fields."

2
If the model has no graph view → click "Create Graph View"

Studio auto-creates a basic graph view. The field configuration then becomes available.

✏️

Step 2 — Set View Name & Chart Type

1
Enter a View Name

The internal name saved with the view. Example: Sales by Month.

2
Select chart type via the Chart buttons: Bar · Line · Pie

Click one to set the default chart type. The active button is highlighted. This sets the type attribute in the graph view XML.

TypeBest for
🏦 BarComparing categories (e.g. sales by product)
📉 LineTrends over time (e.g. revenue per month)
🥧 PieProportional breakdown (e.g. orders by status)
🎯

Step 3 — Add Fields & Set Roles

1
Click "Add" tab or "Add Graph Field" button

Numeric fields default to Meas; all others default to Row.

2
Click a role button (Row / Col / Meas) per field

Active role is highlighted. Clicking active role deactivates it.

3
Remove a field with ✕
RolePurposeNotes
RowX-axis / category grouping / pie segmentsAny non-numeric field
ColSeries grouping (stacked/grouped bar)Disabled for integer, float, monetary fields
MeasY-axis numeric measure / pie segment sizeNumeric fields only
✅ At least one Meas field is required for the chart to display meaningful data.
💾

Step 4 — Save or Reset

1
Click "Save" in the panel footer

Writes view name, chart type, and all field roles to the graph view XML using //graph position="replace".

2
Click "Reset" to discard changes

Reloads the graph field list and chart type from the server.

📅 Calendar View Builder

Configure how records appear in the calendar view — date fields, labels, colour grouping, default mode, quick create.

1️⃣

Step 1 — Switch to Calendar Mode

1
Click the Studio icon, then "Cal" in the view toggle

Hint: "Configure date fields, color grouping, and default view mode."

2
If no calendar view exists → click "Create Calendar View"

Studio auto-creates a basic calendar view and auto-detects the best available date field for Start Date. The config panel then becomes available.

⚙️

Step 2 — Configure Calendar Fields

1
Start Date ✱ (required)

Select a date or datetime field — marks where each calendar event begins. The "Save Calendar Config" button is disabled until a Start Date is selected.

2
End Date (optional)

Date/Datetime field for event end. If not set, each event appears as a single-day/single-time entry.

3
Duration Field (optional)

A float or integer field for event duration in hours. If both End Date and Duration Field are set, Duration Field takes precedence in the calendar view XML.

4
Event Label (optional)

Select a field whose value is shown as the event title on the calendar. Date/datetime and many2one fields are listed.

5
Color By (optional)

Select a many2one field only — events are colour-coded by that field's value, with a colour legend in the calendar sidebar. Selection fields are not supported for calendar colouring in Odoo 19.

6
Default View

Sets the initial calendar display: Day · Week · Month (default) · Year.

7
Quick Create toggle

When enabled (default), clicking an empty slot opens a quick-create dialog. When disabled, a full form opens instead.

💾

Step 3 — Save Calendar Config

1
Click "Save Calendar Config"

The button is disabled until a change is pending (dirty) AND a Start Date is selected. Saves the configuration to the calendar view XML.

💡 After saving, reload the calendar view in the main area to see the updated configuration take effect.

🗓️ Gantt View Builder

Interactive timeline chart powered by Frappe Gantt (bundled locally — no CDN required). Drag bars to reschedule records.

🆕 Phase 29Frappe Gantt v0.6.1
1️⃣

Step 1 — Switch to Gantt Mode

1
Click the Studio icon, then "Gantt" (9th view toggle button)

Hint: "Configure the Gantt chart fields for this model."

2
No separate "Create View" step needed

The Gantt view is rendered as a standalone page. Configuration is stored in ir.config_parameter.

⚙️

Step 2 — Configure the Gantt Chart

1
Chart Title (optional)

Free-text heading shown above the Gantt chart. Example: Project Task Timeline.

2
Start Date ✱ (required)

Select a date or datetime field — determines where each bar begins. "Save Config" and "Open Gantt" buttons are disabled until Start Date is set.

3
End Date (optional)

Date/datetime field for bar end. If left as "none (1-day bars)", each bar spans exactly one day.

4
Task Label (optional)

Select a Char or Text field — its value is displayed as text on each Gantt bar.

5
Color By (optional)

Select a many2one or selection field — records are colour-coded by this field's value.

6
Progress % (optional)

Select a float or integer field (values 0–100). Renders a progress bar inside each Gantt bar showing completion percentage.

7
Group By Field (optional)

Select a many2one or selection field to create swim-lane rows (grouped Gantt). "none (flat list)" shows all bars ungrouped.

8
Default Scale

Initial zoom level of the Gantt timeline.

Scale optionValue stored
Week (default)Week
DayDay
MonthMonth
Quarter DayQuarterDay
Half DayHalfDay
💾

Step 3 — Save & Open Gantt

1
Click "Save Config"

Saves to ir.config_parameter key drkds_studio.gantt_config.{model}. Persists across server restarts. Disabled until Start Date is selected.

2
Click "Open Gantt"

Opens the Gantt chart view in the main content area. Also disabled if no Start Date is selected.

💡 From the Gantt view: drag bars to reschedule records, click a bar to open the record form, use scale buttons (Day / Week / Month zoom) to change the timeline level. The search bar is included for filtering records.
✅ Frappe Gantt v0.6.1 is fully bundled in static/lib/frappe-gantt/ — no npm install, no internet connection, no CDN needed. Each model stores its own separate Gantt config.

🖨️ QWeb Report Designer

Create printable PDF or HTML reports for any model. Choose a layout template, pick fields, edit XML, and print directly from the model.

Studio → Rpt
→
New Report
→
Name + Format + Layout
→
Pick Fields
→
Create
→
Print ⎙ menu
1️⃣

Step 1 — Open the Reports Tab

1
Studio → "Rpt" tab

Shows all reports bound to the current model — both Studio-created (with "studio" badge) and native Odoo reports.

2
Each report row shows 3 action buttons

⎙ Print (preview), </> Edit XML (code editor), 🗑️ Delete (Studio reports only).

➕

Step 2 — Create a New Report

1
Click "New Report" → enter a Name

Required. Becomes the report action name in the Print menu. "Create Report" button is disabled until a name is entered.

2
Select Format: PDF or HTML

PDF = qweb-pdf (downloads a PDF file). HTML = qweb-html (renders inline in the browser).

3
Select a Layout Template (click a card)

Four template cards are available:

TemplateDescription
Simple TableClean label/value rows for each selected field
Invoice StyleColoured header block + info grid + bordered summary table — suitable for billing documents
Two ColumnFields displayed side by side in two columns
Delivery SlipCompact 3-column card grid with green header — suitable for delivery/shipping documents
4
Select a Language field (optional)

Dropdown lists many2one fields pointing to res.partner or res.lang. Selecting one causes the report to auto-print in the recipient's language. Leave as "None (company language)" if not needed.

5
Tick fields to include (checkbox list)

A scrollable checklist shows all suitable model fields. Excluded: Binary, HTML, One2many, Many2many. At least one field must be selected.

6
Click "Create Report"

Generates the QWeb view XML (using lxml — no XML injection risk), creates an ir.actions.report bound to this model. The report immediately appears in the model's Print ⎙ action menu.

💡 Duplicate name detection: if a report with the same generated template name already exists, creation is blocked with an error message.
✏️

Step 3 — Edit Report XML

1
Click the </> icon on any report row

Opens the inline XML editor showing the full <t t-name="..."> QWeb template.

2
Edit the XML in the textarea

Common edits: add/remove <span t-field="o.field_name"/> elements, adjust styles, change layout. Note: t-field renders with Odoo's built-in formatting.

3
Click "Save XML"

XML is validated before saving. Invalid XML is rejected with a clear error message.

4
Click "Cancel" to close without saving

Returns to the report list. Unsaved XML changes are discarded.

⎙

Step 4 — Print & Delete

1
Click the ⎙ print icon on a report row

Triggers the Odoo report action in the current record context. PDF reports download; HTML reports render inline.

2
Click 🗑️ to delete a Studio report

Deletes both the ir.actions.report record and the underlying QWeb ir.ui.view. Only Studio-created reports (with "studio" badge) show the delete button. Native Odoo reports cannot be deleted.

✅ All 4 templates use web.external_layout — your company header and footer are included automatically. Click Refresh in the Rpt tab to reload the report list from the server.

⚙️ Automation Builder

Create and manage base.automation rules with full inline form — triggers, filters, 7 action types.

7 Action TypesMultiple Actions per Rule
Auto tab
→
New Rule
→
Set Trigger
→
Add Actions
→
Save Rule
🎯

Trigger Types

TriggerWhen it fires
on_createWhen a new record is created
on_writeWhen an existing record is updated
on_create_or_writeOn both create and update
on_unlinkWhen a record is deleted
on_changeWhen a specific field value changes
on_timeAt a scheduled time (based on a date field)
⚡

7 Action Types

ActionWhat it doesKey input
Execute Python CodeRun arbitrary PythonCode block (record, env available)
Update the RecordSet a field valueField name + Fixed Value or Python Expression
Create a New RecordCreate a record on same or other modelTarget model + population code
Send EmailSend via a mail templateTemplate selection
Add FollowersSubscribe partners to the threadPartner checklist or dynamic field
Create Next ActivitySchedule a follow-upType, summary, due in, assigned to
Send SMSSend an SMS (requires sms module)SMS template selection
✅ Multiple actions can be added to one rule — they execute in order when the trigger fires.
💡

Example: Auto-assign on Create

Record Created
→
Filter: type='lead'
→
Update: user_id = env.user
→
Send Email: Welcome

🛠️ Server Actions Builder

Create Python server actions and bind them to the model's Action (⚙️) menu.

🛠️

Creating a Server Action

1
Studio → Srv tab

Lists all server actions for this model (both Studio-created and others).

2
Click "New Server Action"

Enter a name and write Python code. Variables: records, env, model.

3
Toggle binding to bind/unbind from Action menu

When bound (green border), the action appears in the ⚙️ Action dropdown on list and form views.

💡 Odoo 19: when unbinding, only set binding_model_id=False and binding_view_types=False. Never set binding_type=False — that raises a validation error.

🔗 Outgoing Webhook Builder

POST JSON payloads to external URLs whenever a model event (create / update / delete) occurs.

🔗

How Webhooks Work

Record Event
→
base.automation fires
→
_fire_outgoing()
→
HTTP POST → URL
⚠️ Odoo 19 safe_eval blocks import statements. Webhooks work by calling env['studio.webhook']._fire_outgoing() internally — never put imports in server action code.
⚙️

Payload

FieldValue
modelTechnical model name (e.g. sale.order)
triggeron_create / on_create_or_write / on_unlink
record_idID of the triggering record
record_namedisplay_name of the triggering record
timestampISO 8601 UTC timestamp

⏰ Scheduled Actions Manager

Create cron jobs that run Python code on a time-based schedule.

⏰

Key Points

1
Studio-created crons are named "Studio: …"

Identified by the cron_name prefix. All other crons are shown read-only.

2
New crons are created inactive by default

Review the code before activating to avoid unintended side effects.

3
Odoo 19: provide both name AND cron_name

name maps to the linked ir.actions.server.name (required). cron_name is the display label on ir.cron.

💡 Use with_context(active_test=False) to see inactive crons — Odoo hides them by default in search queries.

🔢 Sequence Builder

Define formatted sequences like INV/2025/0001 with custom prefix, suffix, padding, and increment.

🔢

Sequence Format Tokens

TokenReplaced withExample
%(year)s4-digit year2025
%(month)s2-digit month03
%(day)s2-digit day09
padding zerosAuto-incremented counter00042
Example: Prefix INV/%(year)s/ + Padding 4 → INV/2025/0001, INV/2025/0002, …
⚙️

Options

OptionDescription
PaddingNumber of digits for the counter (e.g. 4 → 0001)
IncrementStep between sequence numbers (default 1)
Next NumberOverride the next value to be issued
PrefixStatic prefix before counter (supports date tokens)
SuffixStatic suffix after counter (supports date tokens)

🗃️ Custom Model Creator

Create brand-new data models without writing Python — complete with auto-generated views, menus, and access rules.

Models button
→
New Custom Model
→
Enter name
→
Create
→
Open in Editor
🗃️

What Gets Auto-Created

ArtefactDetail
ir.modelModel with state='manual'
x_name fieldAuto-created Char field; Odoo sets it as _rec_name
Form viewMinimal form view named studio.custom.{model}.form
List viewMinimal list view named studio.custom.{model}.list
Window actionir.actions.act_window pointing to the model
Menu itemUnder top-level "Custom" menu (sequence 100)
💡 After creating the model, use Studio's Form and List view builders to add custom fields and configure how the model looks.

🏷️ Fields & Default Values Manager

Create custom fields on any model. Set global, user-specific, or company-specific default values.

🏷️

Field Wizard — Supported Types

CharTextIntegerFloat MonetaryBooleanDateDatetime SelectionMany2oneOne2manyMany2many BinaryHTML
💡 Custom fields get technical names starting with x_ (e.g. x_priority_score). They persist in the database until explicitly deleted.
⚙️

Default Value Scopes

ScopeApplies toUse case
GlobalAll users, all companiesSystem-wide default for a field
CompanyCurrent company onlyCompany-specific default (e.g. tax rate)
UserCurrent logged-in user onlyPersonal preference default
✅ Setting a default on the same field+scope again overwrites the existing default (upsert behaviour).

📝 Selection Field Values Editor

Add or remove values from Selection fields — for both standard and custom fields.

📝

Two-Level UI

Sel tab → Field list
→
Click field
→
View values
→
Add / Delete
⚠️ Odoo 19 blocks creation/deletion of values on base field selections (fields with state != 'manual'). Only custom fields (state = 'manual') allow full CRUD on selection values.
⚠️ Before deleting a value, Studio checks how many records currently use that value. If records exist, deletion is blocked to prevent data inconsistency.

🔀 Model Relations Browser

Visually explore Many2one, One2many, and Many2many links for the current model. Read-only — no changes needed.

🔀

Relation Types

RelationDirectionExtra info shown
Many2oneThis model → Related modelField name, related model label
One2manyThis model ← Child modelField name, inverse field name, child model label
Many2manyThis model ↔ Related modelField name, relation table name, related model label

🔐 Access Rights Manager

Grant or revoke CRUD permissions on any model per user group — with one-click toggle badges.

🔐

Permission Badges

BadgePermissionColour when active
RRead■ Green
WWrite (update)■ Green
CCreate■ Green
DDelete (unlink)■ Green
💡 Only Studio-created rules are clickable/deletable. Standard Odoo access rules are shown as read-only reference.
✅ To filter named groups: use privilege_id != False in Odoo 19 (no category_id on res.groups).

📜 Record Rules Manager

Row-level security — restrict which records a user can see or modify using domain filters.

📜

Rule Options

OptionDescription
DomainPython domain string like [('user_id','=',user.id)]
GlobalApplies to all users (no group restriction)
GroupsRestricts the rule to specific user groups
Read / Write / Create / DeleteWhich operations this rule applies to
⚠️ Odoo 19: ir.rule.global is a Python keyword. Access via r['global'] (NOT r.global_).
💡 The domain is evaluated with user and time available. Example: [('date','>=', (datetime.date.today() - datetime.timedelta(days=30)).strftime('%Y-%m-%d'))]

📧 Email Template Builder

Build reusable Jinja2 email templates. Use them in Automation rules or send manually.

📧

Template Variables

VariableRefers toExample
objectThe triggering record{{ object.name }}
userThe current user{{ user.name }}
companyThe current company{{ company.name }}
ctxTemplate context dict{{ ctx.get('key') }}
⚠️ Odoo 19 template engine: {{ user.email | safe }} is REJECTED (pipe filters not whitelisted). Use {{ user.email }} only.

📨 Email Gateway Manager

Manage mail.alias entries so incoming emails create or update records on your model.

📨

Alias Configuration

FieldDescription
Alias NameLocal part of the email (e.g. sales → sales@yourdomain.com)
Alias DomainYour outgoing mail server domain
Alias ModelModel to create/update when email arrives
Alias DefaultsPython dict of default field values for new records
Thread DetectionWhether to detect existing records by email thread

🔔 Activity Type Manager

Create custom activity types (phone call, upload, follow-up) with default due delays and scope control.

🔔

Activity Type Options

OptionValuesEffect
Categorydefault / upload_file / phonecallChanges icon and behaviour of the activity
Default DelayN days / weeks / monthsPre-fills due date when creating the activity
Scopemodel / globalModel-specific: only on this model. Global: available on all models
💡 Global activity types (scope=global) appear in the activity picker on all models. Model-specific types only appear on their assigned model.

🔖 Saved Filters Manager

Create reusable domain filters that appear as quick-access buttons in the search bar.

🔖

Filter Scope

ScopeWho sees itOdoo 19 implementation
GlobalAll usersuser_ids=[(5,0,0)] (empty M2M)
PrivateCurrent user onlyuser_ids=[(4, uid)]
⚠️ Odoo 19 CRITICAL: ir.filters.user_id was removed. Use user_ids (Many2many to res.users).
✅ The domain is validated via safe_eval before saving. Invalid domain strings are rejected with a clear error message.

⬇️ Data Export Templates Manager

Create named export templates that pre-select which fields to include when exporting model data.

⬇️

How to Use

1
Studio → DExp tab

Shows all export templates for this model.

2
Click "New Export Template"

Enter a name and tick the fields to include. Binary, HTML, and relational fields (O2M) are excluded.

3
Use from the Export dialog

When users export data from a list view, the saved template appears as a preset in the export dialog (under Saved Exports).

⬆️ Import CSV / XLS

Upload a CSV or Excel file, map columns to model fields, and import data in 3 steps.

Upload File
→
Map Columns
→
Review & Import
→
Results
⬆️

Steps

1
Drag & drop or browse for CSV/XLS file

The wizard auto-detects column headers and attempts to auto-map them to model fields by name similarity.

2
Review column mapping

For each CSV column, select the target model field from a dropdown. Unmapped columns are skipped.

3
Click Import

Rows are validated and imported. A results panel shows the count of created/updated records and any row-level errors.

💡 Requires the base_import Odoo module (included in standard Odoo 19).

⚡ Batch Actions

Bind server actions to list and/or form views — so users can run them on selected records from the Action menu.

⚡

Binding & Unbinding

1
Studio → Batch tab

Lists all server actions that can be bound as batch actions for this model.

2
Toggle the binding switch

When ON (green border), the action appears in the ⚙️ Action dropdown on list views when records are selected.

3
Choose binding scope: List / Form / Both

Controls whether the action appears on the list view's multi-select menu, the form view's Action button, or both.

✅ Studio batch actions use the prefix Studio.Batch: for identification. They are ir.actions.server records with binding_model_id set.

📦 Module Export

Export all your Studio customisations as a standard Odoo .zip module — ready to deploy on any server.

Studio settings
→
Export Module
→
Download .zip
→
Install on target
📦

What's Included in the Export

FileContent
__manifest__.pyModule metadata (name, version, depends)
models/custom_models.pyCustom model definitions
security/ir.model.access.csvAccess rules for custom models
views/custom_model_views.xmlForm and list views for custom models
views/view_customizations.xmlStudio view changes on standard models
data/menu_data.xmlCustom menus and window actions
💡 The export uses stdlib zipfile and base64 only — no external dependencies. The browser downloads the zip automatically via Blob URL.
✅ Field selection values are exported via ir.model.fields.selection_ids. External IDs are resolved safely for all records.

🌐 API Info Panel

Browse JSON-RPC endpoints for the current model. Copy ready-to-use Python, JavaScript, or cURL snippets.

🌐

Available Snippets

SnippetPurpose
Python (xmlrpc)Server-to-server integration using xmlrpc.client
JavaScript (fetch)Browser/Node.js integration using fetch API
cURLCommand-line testing with curl
💡 The API panel is read-only. It auto-generates code for the current model's standard CRUD endpoints: search_read, create, write, unlink.
🔗

JSON-RPC Endpoint

All Odoo JSON-RPC calls go to:

POST /web/dataset/call_kw

With body: {"model":"…","method":"search_read","args":[…],"kwargs":{…}}