🎨 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":{…}}