A Complete Overview of Fields in Odoo 19
Fields are the backbone of any Odoo application. In Odoo 19, fields define how data is stored, displayed, validated, and interacted with across models, views, and business logic. Whether you are working on ERP modules, custom addons, or large-scale enterprise solutions, understanding Odoo fields deeply is essential. This guide provides a complete, structured, and practical overview of all major field types in Odoo 19, with explanations, examples, and real-world use cases.
1. What Are Fields in Odoo?
In Odoo, a field represents a column in a database table and an attribute of a model (`models.Model`). Fields are declared as Python class attributes and are handled by Odoo’s ORM (Object Relational Mapping).
from odoo import models, fields
class Product(models.Model):
_name = 'custom.product'
name = fields.Char(string='Product Name')
Each field controls:
- Data type (string, number, date, relation, etc.)
- Database storage
- UI rendering in views
- Validation and constraints
2. Basic (Simple) Field Types
2.1 Char
Stores short text (VARCHAR).
name = fields.Char(string="Name", required=True)
Use case: Names, titles, codes
2.2 Text
Stores long text (TEXT).
description = fields.Text(string="Description")
Use case: Notes, comments, descriptions
2.3 Html
Stores HTML content with rich-text editor support.
content = fields.Html(string="Content")
Use case: Email templates, product descriptions
2.4 Integer
Stores whole numbers.
quantity = fields.Integer(string="Quantity")
2.5 Float
Stores decimal numbers.
price = fields.Float(string="Price")
2.6 Monetary
Float field linked with currency.
price = fields.Monetary(string="Price", currency_field='currency_id')
currency_id = fields.Many2one('res.currency')
Use case: Financial values
2.7 Boolean
Stores True/False.
active = fields.Boolean(string="Active", default=True)
3. Date & Time Fields
3.1 Date
Stores date only.
start_date = fields.Date(string="Start Date")
3.2 Datetime
Stores date and time (UTC-based).
created_on = fields.Datetime(string="Created On")
4. Selection Fields
Selection fields allow choosing one value from a predefined list.
state = fields.Selection([
('draft', 'Draft'),
('confirmed', 'Confirmed'),
('done', 'Done')
], string="Status", default='draft')
Use case: Status workflows, categories
5. Relational Fields (ORM Power)
5.1 Many2one
Links one record to another.
partner_id = fields.Many2one('res.partner', string="Customer")
Database: Foreign key
5.2 One2many
Inverse of Many2one (not stored directly).
order_line_ids = fields.One2many('sale.order.line', 'order_id', string="Order Lines")
5.3 Many2many
Many-to-many relationship.
tag_ids = fields.Many2many('product.tag', string="Tags")
Database: Relation table
6. Computed Fields
Fields whose value is calculated dynamically.
amount_total = fields.Float(compute='_compute_amount')
@api.depends('price', 'quantity')
def _compute_amount(self):
for rec in self:
rec.amount_total = rec.price * rec.quantity
Key Options
- compute
- store=True (persist in DB)
- @api.depends
7. Related Fields
Fields that mirror another field.
partner_email = fields.Char(related='partner_id.email', store=True)
Use case: Avoid joins, improve reporting
8. Default Values
is_active = fields.Boolean(default=True)
name = fields.Char(default=lambda self: 'New')
9. Field Attributes (Very Important)
| Attribute | Description |
|---|---|
| string | Label shown in UI |
| required | Mandatory field |
| readonly | Read-only |
| index | Add DB index |
| copy | Copy on duplication |
| help | Tooltip text |
| tracking | Chatter tracking |
Example:
name = fields.Char(
string="Name",
required=True,
tracking=True,
help="Enter record name"
)
10. Domain & Context in Fields
Domain
Filters selectable records.
partner_id = fields.Many2one(
'res.partner',
domain=[('is_company', '=', True)]
)
Context
Pass extra parameters.
partner_id = fields.Many2one(
'res.partner',
context={'show_address': True}
)
11. Onchange Fields
Update values on UI change (no DB write).
@api.onchange('quantity')
def _onchange_quantity(self):
if self.quantity < 0:
self.quantity = 0
12. Constraints (Validation)
SQL Constraint
_sql_constraints = [
('unique_name', 'unique(name)', 'Name must be unique!')
]
Python Constraint
@api.constrains('age')
def _check_age(self):
for rec in self:
if rec.age < 18:
raise ValidationError('Age must be 18+')
13. Company & Multi-Company Fields
company_id = fields.Many2one(
'res.company',
default=lambda self: self.env.company
)
14. Special & Advanced Fields
- Binary – File upload
- Image – Image with resizing
- Reference – Dynamic model reference
- Properties – Dynamic property fields
image_1920 = fields.Image(max_width=1920, max_height=1920)
15. Fields & Views Relationship
Fields control rendering in:
- Form View
- Tree View
- Kanban View
- Search View
Example:
xml
16. Best Practices
- Use store=True only when needed
- Prefer related over duplicate fields
- Always define string
- Index frequently searched fields
- Avoid heavy compute without depends
17. Conclusion
Fields in Odoo 19 are powerful, flexible, and deeply integrated with the ORM, UI, and business logic. Mastering fields means mastering Odoo development itself.
If you understand:
- Field types
- Relations
- Computed & related fields
- Constraints & attributes