Skip to Content

Custom Fields in Odoo: The Complete Guide

Learn how to extend any Odoo model with custom fields using Odoo Studio or Python, and why it matters for your business
March 6, 2026 by
Custom Fields in Odoo: The Complete Guide
Dasolo
| No comments yet

Every business is different. Your team tracks information that no standard software anticipates, and that is exactly where custom fields in Odoo come in.


Instead of forcing your workflows to fit a rigid data model, Odoo lets you add new fields to almost any record, whether that is a customer, a sale order, a product, or an invoice. You decide what data to capture, and Odoo stores it alongside everything else.


This guide covers everything you need to know: what custom fields are, how they work under the hood, how to create them with or without code, and how to use them in a way that keeps your Odoo instance clean and maintainable.

What Is a Custom Field in Odoo


A custom field is a database field you add to an existing Odoo model, beyond what comes out of the box. It stores a specific piece of information tied to a record, exactly like a native field would.


In Odoo, custom fields are identified by the x_ prefix. Fields created through Odoo Studio use names like x_studio_priority_level, while fields added programmatically might use a prefix specific to your project, such as x_dasolo_cost_center.


From the user interface, a custom field looks and behaves exactly like any standard field. It can appear in forms, list views, filters, group-by options, and reports. Users who do not know the technical side will never notice the difference.


Available Field Types

Odoo supports a wide range of field types for custom fields, covering most data needs:

  • Text (Char): Short text, like a reference code or a label
  • Long Text: Multi-line free text for notes or descriptions
  • Integer: Whole numbers, useful for counts or scores
  • Decimal (Float): Numbers with decimals, for measurements or rates
  • Monetary: Currency-aware amount, linked to a currency field
  • Boolean: A true/false checkbox
  • Date / Date & Time: Calendar date or timestamp
  • Selection: A fixed dropdown list of options
  • Many2one: A link to a single record in another model
  • One2many: A list of related records from another model
  • Many2many: Multiple records linked from another model
  • Binary: File attachment
  • HTML: Rich text content

Choosing the right field type from the start saves a lot of trouble later. A selection field is almost always better than a free-text field when the set of possible values is known in advance.

How the Field Works


Odoo is built on a framework called the Odoo ORM (Object-Relational Mapping). Every form, list view, and record you see in the interface is backed by a Python model that maps to a database table. When you add a custom field, Odoo registers it in the ORM and creates the corresponding column in PostgreSQL automatically.


This is what makes the Odoo data model flexible: you are not patching the source code. You are extending the model through a metadata layer stored in the ir.model.fields table. Odoo reads that table at startup and builds the fields dynamically.


Fields Defined in Code vs. Fields Defined in the Database

In standard Odoo development, fields are defined directly in Python model classes using the Odoo framework. A typical field definition looks like this:


from odoo import models, fields

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    cost_center = fields.Char(string='Cost Center')

Custom fields created via the UI or API follow a different path: they are stored with state = 'manual' in ir.model.fields and loaded at runtime. Both approaches produce a real database column and behave identically from the user perspective.


Relational Fields and Reciprocity

When you create a Many2one custom field pointing to another model, Odoo expects a matching One2many field on the other side. This is not just a convention: it is how the Odoo ORM navigates relationships between records.


For example, if you add a x_project_id (Many2one to project.project) on a sale order, you should also add x_sale_order_ids (One2many back to sale.order) on the project model. Without this, navigation from the project to its linked orders is not possible through the standard interface.


Computed Custom Fields

Odoo computed fields are fields whose value is calculated automatically based on other fields, rather than entered by the user. In technical customizations, you define a Python method and link it to the field using the compute parameter. These fields are read-only and update whenever their dependencies change.


Computed fields are powerful but require code. They cannot currently be created through Odoo Studio without developer mode and some Python knowledge.

Business Use Cases


Custom fields appear in nearly every Odoo project we work on at Dasolo. Here are five common scenarios from real business workflows.

1. CRM: Qualifying Leads More Precisely

Standard Odoo leads capture contact details and pipeline stage, but many sales teams need more. A Selection field for "Customer Industry" or a Many2one linking to an internal "Market Segment" model lets sales reps qualify leads faster and enables management to report on pipeline by segment.


2. Sales: Tracking Internal Project Codes

Companies that bill clients by project often need to attach an internal project code or budget reference to each quotation or sale order. A simple Char field called "Project Code" on sale.order makes this possible without a full project management integration. The field appears on printed documents and can be used to filter and group orders in reports.


3. Inventory: Product-Specific Attributes

Beyond Odoo's standard product attributes, businesses sometimes need to track technical specifications unique to their industry. A manufacturer might add fields for "Warranty Period (months)" (Integer), "Certification Standard" (Selection), or "Country of Origin" (Many2one to res.country). These fields integrate naturally with the product form and are available in inventory reports.


4. Accounting: Budget and Cost Center Allocation

Finance teams frequently need to tag invoices or journal entries with a cost center or budget line. A Many2one field on account.move pointing to a custom "Cost Center" model allows detailed cost allocation without modifying Odoo's analytic accounting setup. Filters, pivot tables, and exports all respect the field immediately after creation.


5. HR: Custom Onboarding Data

HR departments often collect data during onboarding that does not fit standard employee fields: contract types specific to a country, internal skill categories, or fleet assignment references. Custom fields on hr.employee keep this information inside Odoo rather than in a separate spreadsheet, making it searchable and reportable.

Creating or Customizing the Field


There are two main ways to create custom fields in Odoo. The right choice depends on your technical resources and how complex the field needs to be.


Option 1: Odoo Studio (No Code)

Odoo Studio fields are the fastest path for business users. With Studio enabled, you can add a new field to any view in a few clicks:

  1. Open the app and record type where you want the field (for example, a sale order form)
  2. Click the pencil icon to enter Studio edit mode
  3. Drag a field type from the left panel onto the form
  4. Set the field label, technical name, and any additional properties
  5. Save and exit Studio

Studio creates the field in ir.model.fields with the x_studio_ prefix and adds it directly to the view. No deployment or server restart is needed. This is the recommended approach for straightforward fields that do not require custom logic.


Option 2: Technical Customization via the API

For teams working on Odoo customization projects, fields can be created programmatically using the XML-RPC API or by writing a Python module. This is the right path when you need computed fields, complex domain filters, or fields that should be part of a version-controlled codebase.


Using the API, creating a custom selection field on a sale order looks like this:


# Find the model ID for sale.order
model = models.execute_kw(
    db, uid, api_key,
    'ir.model', 'search_read',
    [['model', '=', 'sale.order']],
    {'fields': ['id', 'name']}
)[0]

# Create the custom field
field_id = models.execute_kw(
    db, uid, api_key,
    'ir.model.fields', 'create',
    [{
        'name': 'x_project_type',
        'field_description': 'Project Type',
        'model_id': model['id'],
        'ttype': 'selection',
        'selection': [('internal', 'Internal'), ('client', 'Client'), ('rd', 'R&D')],
        'state': 'manual',
    }]
)

This is part of the standard Odoo developer guide workflow for adding fields without modifying source files. It is especially useful for remote configurations and automated deployment scripts.


For a full Python module approach, fields are defined in a model class and loaded via the standard Odoo module mechanism. This is the most maintainable option for fields that will persist across upgrades and need to be tracked in version control.


Adding the Field to a View

Creating a field does not automatically make it visible in the interface. You also need to add it to the relevant form or list view. With Studio, this is done at the same time as field creation. With technical customization, you either modify the view XML directly or create an inherited view that injects the field into the right position.


Best Practices


Custom fields are easy to create, but a poorly planned field architecture creates problems that are hard to fix later. These are the practices that keep things clean.


Use Selection Fields Over Free Text Whenever Possible

If the set of possible values is known in advance, always use a Selection field instead of a Char field. Free text leads to inconsistent entries ("Client", "client", "CLIENT", "Cl.") that break filters and reports. A dropdown enforces consistency at zero extra cost.


Name Fields Clearly and Consistently

The technical name (x_project_type) should reflect the content, not the position on the form. A field named x_field_1 is impossible to maintain six months later. Use a consistent naming convention and document what each field is for.


Do Not Over-Extend Native Models

Adding ten custom fields to sale.order is usually a sign that a custom model would serve better. If a group of fields belongs together and represents a new entity in your business (a project, a contract, a certification), consider creating a custom model and linking it with a Many2one field instead.


Always Test on a Staging Database

Before adding fields to a production instance, test on a copy of the database. Field creation is mostly safe, but adding a field to the wrong model, or with the wrong type, can require manual cleanup. A staging environment catches these issues early.


Document Your Custom Fields

Keep a record of every custom field you add: the model, the technical name, the purpose, and who requested it. Odoo implementations accumulate fields over time, and without documentation it becomes impossible to know which ones are still in use and which ones can be removed.


Use the Right Tool for Computed Logic

If a field's value depends on other fields, use a computed field rather than asking users to fill it in manually. This avoids inconsistencies and reduces data entry errors. Computed fields are part of core Odoo Python fields functionality and are well-documented in the official Odoo technical tutorial.

Common Pitfalls


Even experienced teams run into the same issues with custom fields. Here are the ones that come up most often.


Forgetting the One2many When Creating a Many2one

This is the most common technical mistake. If you add a Many2one field on model A pointing to model B, and you do not create the corresponding One2many on model B, navigation from B to A is broken. Users cannot see related records from the other side of the relationship. Always create both fields together.


Deleting a Field That Contains Data

Deleting a custom field permanently removes the database column and all the data it contains. There is no undo. If there is any chance the field or its data will be needed in the future, archive or hide the field instead of deleting it.


Creating Fields Directly in Production

Making changes directly on a live production database, without testing on staging first, is a risk even for simple field additions. If something goes wrong with the view configuration, users get errors. Always validate on a test environment first.


Naming Conflicts with Standard Fields

Odoo will reject a field name that already exists on the model, but it is easy to accidentally create a field that shadows a field from a module you install later. Using a company-specific prefix (such as x_acme_) for your custom fields reduces this risk considerably.


Adding a Field to the View Without Thinking About UX

Just because a field can be added to a form does not mean it should be visible by default. Cluttered forms slow users down. If a field is only relevant in specific contexts, put it in a separate tab or make it conditionally visible using domain-based invisibility rules.


Mixing Studio Fields and Technical Fields Inconsistently

When a project combines Studio customization and code-based customization, you can end up with fields that have overlapping purposes or conflicting names. Agree on a strategy at the start of the project: either use Studio for all no-code fields and code for complex logic, or use code for everything. Mixing both without a clear plan creates maintenance headaches.

Conclusion


Custom fields are one of the simplest and most impactful ways to adapt Odoo to your business. They require no source code modifications, integrate naturally with the rest of the platform, and give users the exact data capture they need without workarounds.

The key is to plan before you build. Choose the right field type, name things clearly, respect relational field conventions, and document what you create. A well-designed field architecture makes your Odoo instance easier to maintain and easier to evolve as your business grows.


Whether you are using Odoo Studio for quick no-code fields or writing Python modules as part of a broader Odoo customization project, the underlying principles are the same: match the field to the data, keep the model clean, and always test before deploying to production.

At Dasolo, we help companies implement, customize, and optimize Odoo to fit their real workflows. Whether you need a few custom fields added to your existing setup or a full custom module built from scratch, our team is here to help.

Reach out to us if you need guidance on your Odoo implementation. We are happy to review your current setup and suggest the cleanest path forward.

Custom Fields in Odoo: The Complete Guide
Dasolo March 6, 2026
Share this post
Sign in to leave a comment