Skip to Content

Selection Field in Odoo: The Complete Guide

Everything you need to know about the Selection field in the Odoo data model, from basic usage to technical customization
March 6, 2026 by
Selection Field in Odoo: The Complete Guide
Dasolo
| No comments yet

Introduction


Every time a user picks a lead priority, selects a payment method, or marks a product as active or archived in Odoo, they are most likely interacting with a Selection field. It is one of the most practical field types in the Odoo framework, and one of the most important to understand if you want to build clean, reliable data models.


Unlike a free-text field where users can type anything, the Selection field restricts input to a predefined list of choices. That constraint is the whole point. It keeps your data consistent, makes filtering and reporting more accurate, and prevents the kind of typos and variations that quietly break aggregations and dashboards over time.


This guide covers everything from what the field stores and how it appears in the interface, to creating and customizing it through Odoo Studio, Python modules, or the XML-RPC API. You will also find practical examples from real business workflows and a list of common mistakes to avoid.

What is the Selection Field in Odoo


In the Odoo ORM, the Selection field stores a string value chosen from a fixed list of options. Each option is defined as a key-value pair: the key is what gets saved in the database, and the label is what the user sees in the interface.


For example, a priority field might be defined with the following options:

priority = fields.Selection([
    ('0', 'Normal'),
    ('1', 'Low'),
    ('2', 'High'),
    ('3', 'Very High'),
], string='Priority', default='0')

In this example, '0', '1', '2', and '3' are the keys stored in the database. The labels Normal, Low, High, and Very High are what users see on screen. This separation matters a lot when it comes to changing labels later without breaking existing records.


In the interface, a Selection field appears as a dropdown list in form views. In list views, it shows the human-readable label. When using the badge widget, each option is rendered as a colored tag, which makes the value immediately visible in dense list views.


In Odoo Studio, this field type is called a Selection field. When created through Studio, it gets an x_studio_ prefix. When created via code or the XML-RPC API, you choose the technical name.

How the Field Works


In the Odoo data model, Selection fields are stored in PostgreSQL as a VARCHAR column. The database only ever stores the key, never the label. This is important to keep in mind when writing domain filters or server actions, since you need to use the key, not the human-readable value.


For example, to search for all leads with high priority, your domain would be [('priority', '=', '2')], not [('priority', '=', 'High')].

Key Field Attributes

Here are the most important properties of a Selection field in the Odoo framework:

  • selection: The list of (key, label) tuples defining the available options. This can also be a method name (string) that returns a list dynamically.
  • default: The key of the option to use when no value has been set yet. If omitted, the field starts empty.
  • required: Forces the user to pick an option before saving. Combined with a default value, this is a common pattern for status fields.
  • selection_add: Used in module inheritance to add new options to an existing Selection field without redefining the whole list. This is the correct approach when extending a native field.
  • ondelete: Works alongside selection_add to define what happens to records with a deleted option when the module that added it is uninstalled.

Static vs Dynamic Selection Lists

By default, the list of options is defined statically in the field declaration. But you can also pass a method name as a string to the selection parameter. Odoo will call that method at runtime to build the list, which lets you show different options depending on the current user, the current company, or any other context.


contract_type = fields.Selection(
    selection='_get_contract_types',
    string='Contract Type'
)

def _get_contract_types(self):
    if self.env.user.has_group('hr.group_hr_manager'):
        return [('permanent', 'Permanent'), ('fixed', 'Fixed Term'), ('interim', 'Interim')]
    return [('permanent', 'Permanent'), ('fixed', 'Fixed Term')]

How It Appears in Views

In a form view, a Selection field renders as a standard dropdown. You can also use the widget="badge" attribute to render it as a colored label, which works well in list and kanban views for status fields. The widget="radio" attribute renders the options as inline radio buttons, which suits fields with a small number of choices where you want all options visible at once.


Interaction with the Odoo ORM

Reading and writing Selection fields in the Odoo ORM works straightforwardly. You assign the key directly, and the framework handles the display mapping automatically. When reading a record through the XML-RPC API with fields_get, the selection attribute of the field includes the full list of [key, label] pairs, which you can use to build your own display logic in external tools.


Business Use Cases


The Selection field appears across virtually every module in a standard Odoo implementation. Here are five concrete examples from common business workflows.


CRM: Lead Priority and Pipeline Stage Type

The priority field on CRM leads is a native Selection field with four levels: Normal, Low, High, and Very High. Sales teams use it to focus their attention on the most promising opportunities. It feeds directly into the Kanban view color coding and can be used in automated actions to trigger follow-up tasks when a lead is escalated. Getting the priority distribution right is one of the first data quality improvements most CRM teams make after going live.


Sales: Payment Term and Invoice Policy

The invoice_policy field on products is a Selection field that controls whether invoicing is based on ordered quantities or delivered quantities. This single field determines the entire billing flow for a product. Similarly, the billing mode on subscription contracts uses a Selection field to distinguish between prepaid and postpaid billing cycles. Both of these are good examples of Selection fields that have significant downstream consequences on financial workflows.


Inventory: Product and Lot Quality States

In manufacturing and quality control workflows, Selection fields are used to track the state of lots, serial numbers, and repair orders. The repair order state field, for instance, moves through values like draft, confirmed, under repair, ready, and done. Each transition can trigger automated emails, inventory moves, or accounting entries. The Selection field acts as the control point that the entire workflow is built around.


Accounting: Payment Method and Journal Type

The journal type field in Odoo Accounting is a Selection field that distinguishes between sale journals, purchase journals, cash journals, and bank journals. Odoo uses this value to apply the correct posting logic, determine which accounts are available, and restrict certain operations to the right journal types. This is a good example of a Selection field that controls business rules rather than just labeling a record.


HR: Employment Type and Contract Status

HR teams use Selection fields to track employment types, contract statuses, and leave request states. The contract status, for example, moves from new to open to expired or cancelled. Automations can notify the HR manager a month before a contract expires, trigger onboarding checklists when a new employee starts, and update payroll rules based on the employment type. The Selection field holds the state that drives all of this logic.

Creating or Customizing the Selection Field


There are three main ways to add a Selection field to an Odoo model, depending on your setup and whether you need the change to be version-controlled or applied programmatically.


Using Odoo Studio (No Code)

Odoo Studio is the built-in low-code tool for adding fields without writing any Python. To add a Selection field through Studio:

  1. Open Odoo Studio from the main menu.
  2. Navigate to the form where you want the field.
  3. Drag a Selection field from the sidebar onto the form.
  4. Add your options in the field properties panel, entering a label for each choice.
  5. Optionally set a default value and mark the field as required.
  6. Save and close Studio.

Studio stores each option with an auto-generated key and the label you provided. The field gets an x_studio_ prefix and is added to the form view automatically. This is the fastest approach for adding a Selection field during a business analysis session with a client.


Using Python in a Custom Module

For developers building Odoo modules, Selection fields are defined in Python model files. This is the recommended approach for customizations that need to be version-controlled and deployed across multiple environments:

from odoo import fields, models

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

    x_delivery_slot = fields.Selection([
        ('morning', 'Morning (8h - 12h)'),
        ('afternoon', 'Afternoon (13h - 17h)'),
        ('evening', 'Evening (18h - 20h)'),
    ], string='Delivery Slot', default='morning')

After defining the field, you add it to the relevant view XML file so it appears in the interface. Odoo handles the database column creation when you install or upgrade the module.


When extending a native field with new options, use selection_add instead of redefining the field:

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

    state = fields.Selection(
        selection_add=[('custom_approval', 'Pending Approval')],
        ondelete={'custom_approval': 'set default'}
    )

Using the XML-RPC API

If you are managing Odoo customizations programmatically, for example as part of a deployment pipeline or a remote configuration notebook, you can create Selection fields via the XML-RPC API:

field_id = models.execute_kw(
    ODOO_DB, uid, ODOO_API_KEY,
    'ir.model.fields', 'create',
    [{
        'name': 'x_contract_category',
        'field_description': 'Contract Category',
        'model_id': model_id,
        'ttype': 'selection',
        'selection': "[('standard', 'Standard'), ('premium', 'Premium'), ('custom', 'Custom')]",
        'state': 'manual',
    }]
)

Note that when creating a Selection field through the API, the selection value is passed as a string representation of the Python list. The state: manual value tells Odoo this field was created manually, which is the correct setting for fields created through Studio or the API. This is how Dasolo handles remote field creation for clients as part of automated configuration scripts.


Best Practices


1. Use meaningful and stable keys

The key is what gets stored in the database and used in domain filters, automated actions, and server-side logic. Choose a key that clearly describes the option and that you will not need to change later. Short lowercase strings work well: 'draft', 'confirmed', 'cancelled'. Avoid numeric keys unless the sequence genuinely matters, because they make your code harder to read and understand months later.


2. Keep the list short and exhaustive

A Selection field with more than eight or ten options is usually a signal that the field is trying to do too much. If the list keeps growing, consider whether a Many2one relation to a configuration model would be more appropriate. That gives users the ability to manage the options themselves through the interface, without requiring a developer to update code or a database field definition.


3. Always set a default for required fields

If a Selection field is required, also set a sensible default value. This prevents validation errors when records are created programmatically, through imports, or via the API, where the user is not present to make a selection. The default should represent the most common or least committed state in the workflow.


4. Use selection_add when extending native fields

If you need to add options to an existing Odoo field in a custom module, use selection_add rather than redefining the full field. This is safer and more compatible with other modules that may also extend the same field. Always pair it with the ondelete parameter to handle what happens when your module is uninstalled.


5. Use the badge widget for visibility in list views

In list and kanban views, the default rendering of a Selection field is just text. Adding the widget="badge" attribute in the view XML turns each value into a colored label, making the field much easier to scan at a glance. This is especially useful for status fields where users need to quickly identify records that need attention.


Common Pitfalls


Changing a key breaks existing data

The label of a Selection option can be changed safely at any time, since only the key is stored in the database. The key, however, must never change once records exist with that value. If you rename a key, all existing records with the old key will display an empty or invalid value in the interface, and any domain filters or automations using the old key will silently stop working. If a key genuinely needs to change, you must run a data migration script to update all existing records first.


Removing an option leaves orphaned records

If you remove an option from the list while records still hold that key, those records will show a missing or broken value. Before removing any option, search for records that still use it and either update them to a valid value or archive them. This is a common issue during data cleanup projects when the list of options was designed without enough analysis upfront.


Using the label instead of the key in domain filters

A very common mistake, especially for less technical users writing automation rules in the Odoo interface, is to filter by the human-readable label rather than the stored key. This produces a domain that returns zero results without raising an error, which can be difficult to diagnose. Always check the field definition to confirm which key corresponds to which label before writing a filter.


Using a Selection field where a Many2one is more appropriate

If the list of options changes frequently, if users need to manage it themselves without developer involvement, or if the options carry additional attributes like a color, a sequence, or a linked account, then a Many2one relation to a configuration model is the better choice. Selection fields are ideal for stable, developer-managed lists. For anything more dynamic, Many2one is more maintainable in the long run.


Not handling the empty value in server-side logic

A Selection field that is not required can hold a False value when no option has been selected. If your Python code or automated action compares the field value to a string without first checking for False, you will get unexpected behavior or errors. Always handle the empty case explicitly in server actions and computed fields that depend on a Selection field.

Conclusion


The Selection field is one of those field types that looks simple but has real depth once you understand how it works under the hood. Knowing the difference between a key and a label, understanding when to use selection_add versus redefining a field, and recognizing when a Many2one would serve you better are the kinds of distinctions that separate a well-designed Odoo implementation from one that causes problems a year down the road.


Whether you are adding a contract type through Odoo Studio, defining a delivery slot field in a custom Python module, or creating a quality state field through the API, the patterns described in this guide give you what you need to make the right decision for your use case.

In the Odoo data model, the Selection field is one of the primary tools for enforcing data quality at the source. Used well, it keeps your records clean, your reports accurate, and your automations reliable.

At Dasolo, we help companies implement, customize, and optimize Odoo across all departments. Whether you need help designing a clean data model, adding custom fields to your workflows, or building a full Odoo module from scratch, our team is here to help. Reach out to us and let's talk about your Odoo project.

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