Field Types Overview
| Type | Python | Database | Use For |
|---|---|---|---|
| Char | fields.Char | VARCHAR | Short text (name, code, email) |
| Text | fields.Text | TEXT | Long text (description, notes) |
| Html | fields.Html | TEXT | Rich HTML content |
| Integer | fields.Integer | INTEGER | Whole numbers (quantity, count) |
| Float | fields.Float | NUMERIC | Decimal numbers (weight, rate) |
| Monetary | fields.Monetary | NUMERIC | Currency amounts (price, total) |
| Boolean | fields.Boolean | BOOLEAN | True/false flags |
| Date | fields.Date | DATE | Dates without time |
| Datetime | fields.Datetime | TIMESTAMP | Dates with time (UTC) |
| Selection | fields.Selection | VARCHAR | Dropdown choices |
| Many2one | fields.Many2one | INTEGER (FK) | Link to one record |
| One2many | fields.One2many | Virtual | Reverse of Many2one |
| Many2many | fields.Many2many | Relation table | Link to many records |
| Binary | fields.Binary | BYTEA/file | File uploads, images |
| Image | fields.Image | BYTEA/file | Images with auto-resize |
| Json | fields.Json | JSONB | Structured JSON data |
Common Parameters
# Parameters available on ALL field types:
name = fields.Char(
string='Display Name', # Label shown in UI
help='Tooltip text', # Help text on hover
required=True, # Cannot be empty
readonly=True, # Cannot be edited
index=True, # Create database index
default='value', # Default value
copy=True, # Copy when duplicating record
groups='base.group_user', # Only visible to this group
tracking=True, # Log changes in chatter
store=True, # Store in database (for computed)
compute='_compute_name', # Compute method
)Char & Text
name = fields.Char(string='Name', required=True, size=128)
email = fields.Char(string='Email')
notes = fields.Text(string='Notes')
description = fields.Html(string='Description', sanitize=True)
# Char: single line, VARCHAR in DB, optional size limit
# Text: multi-line, TEXT in DB, no size limit
# Html: rich text with WYSIWYG editor, sanitized for XSSNumbers
quantity = fields.Integer(string='Quantity', default=1)
weight = fields.Float(string='Weight (kg)', digits=(10, 3)) # 3 decimal places
price = fields.Monetary(string='Price', currency_field='currency_id')
currency_id = fields.Many2one('res.currency', default=lambda self: self.env.company.currency_id)
# Integer: whole numbers only
# Float: decimal, digits=(precision, scale)
# Monetary: like Float but with currency widget in UIDate & Datetime
birth_date = fields.Date(string='Birth Date')
created_at = fields.Datetime(string='Created At', default=fields.Datetime.now)
# Date: stored as Python date object
# Datetime: stored in UTC, displayed in user's timezone
# Useful methods:
fields.Date.today() # Today's date
fields.Datetime.now() # Current datetime (UTC)
fields.Date.to_string(date) # Convert to string
fields.Date.from_string(str) # Convert from stringSelection
status = fields.Selection([
('draft', 'Draft'),
('confirmed', 'Confirmed'),
('done', 'Done'),
('cancelled', 'Cancelled'),
], string='Status', default='draft', required=True)
priority = fields.Selection([
('0', 'Normal'),
('1', 'Low'),
('2', 'High'),
('3', 'Urgent'),
], string='Priority', default='0')
# Stored as VARCHAR in DB (the first value in each tuple)
# Displayed as dropdown in UIRelational Fields
# Many2one: link to ONE record of another model
partner_id = fields.Many2one(
'res.partner',
string='Customer',
ondelete='restrict', # restrict, cascade, set null
domain=[('is_company', '=', True)], # Filter options
)
# One2many: reverse of Many2one (virtual field)
order_line_ids = fields.One2many(
'sale.order.line', # Related model
'order_id', # Many2one field on related model
string='Order Lines',
)
# Many2many: link to MANY records
tag_ids = fields.Many2many(
'project.tags', # Related model
'project_task_tag_rel', # Relation table name (optional)
'task_id', # Column for this model (optional)
'tag_id', # Column for related model (optional)
string='Tags',
)Binary & Image
# Binary: file upload
attachment = fields.Binary(string='File', attachment=True)
attachment_name = fields.Char(string='Filename')
# Image: auto-resizes to multiple sizes
avatar = fields.Image(string='Avatar', max_width=1920, max_height=1920)
# attachment=True: store in filestore (not database)
# attachment=False: store as base64 in database (not recommended for large files)Json (Odoo 16+)
# Store structured data as JSONB
metadata = fields.Json(string='Metadata')
# Usage:
record.metadata = {'color': 'red', 'sizes': ['S', 'M', 'L']}
color = record.metadata.get('color') # 'red'Common Patterns
# Name + code pattern:
name = fields.Char(required=True)
code = fields.Char(required=True, index=True)
# Active flag (soft delete):
active = fields.Boolean(default=True)
# Sequence (ordering):
sequence = fields.Integer(default=10)
# Company field (multi-company):
company_id = fields.Many2one('res.company', default=lambda self: self.env.company)
# User field (assignment):
user_id = fields.Many2one('res.users', string='Responsible', default=lambda self: self.env.user)DeployMonkey
Claude Code generates Odoo models with correct field types from natural language descriptions. Describe your data model in plain English, and the AI creates the Python model with appropriate field types, parameters, and constraints.