Skip to Content

14 - Understanding Field Types: Basic vs. Relational

Welcome back! Now that we know how to create models and even reuse them with Abstract Models, it is time to look at the data itself.

If an Odoo Model is a table in your PostgreSQL database, then Fields are the columns inside that table. Understanding how to choose the right field type is one of the most important skills for an Odoo developer.

In Odoo, fields are divided into two main categories: Basic Fields (storing simple data) and Relational Fields (linking models together). Let's dive in!


1. Basic Fields (Storing Simple Data)

Basic fields store direct values like text, numbers, or dates. Here are the most common ones you will use every day:

  • Char: Used for short text strings (like names or titles). Usually displayed as a single-line input.

  • Text: Used for longer text (like descriptions or notes). Displayed as a multi-line text box.

  • Integer: Used for whole numbers (like quantities).

  • Float: Used for decimal numbers (like prices or weights).

  • Boolean: A simple True/False field. Displayed as a checkbox.

  • Date / Datetime: Used to store calendar dates or exact times.

  • Selection: A drop-down list where the user can choose one option from a fixed list.

Here is what they look like in code:

from odoo import models, fields

class ProductDetails(models.Model):
_name = 'product.details'
_description = 'Product Details'

name = fields.Char(string='Product Name', required=True)
description = fields.Text(string='Description')
quantity_in_stock = fields.Integer(string='Quantity')
price = fields.Float(string='Price', digits=(10, 2))
is_available = fields.Boolean(string='Available for Sale', default=True)
release_date = fields.Date(string='Release Date')
# Selection fields take a list of tuples: [('database_value', 'User Facing String')]
status = fields.Selection([
('draft', 'Draft'),
('active', 'Active'),
('archived', 'Archived')
], string='Status', default='draft')


2. Relational Fields (The Heavy Lifters)

Odoo is a relational system. A Sales Order isn't very useful unless it is linked to a Customer. An Invoice isn't useful unless it is linked to a Product. Relational fields are how we connect different models together.

There are three types of relational fields:

A. Many2one (fields.Many2one)

This is the most common relational field. It links Many records of the current model to One record in another model. Example: Many employees can belong to One department. On the hr.employee model, you use a Many2one field to select their department.

# Links this model to the 'res.partner' (Contact) model
customer_id = fields.Many2one('res.partner', string='Customer', ondelete='cascade')

B. One2many (fields.One2many)

This is the exact opposite of Many2one. It links One record in the current model to Many records in another model. Crucial Rule: A One2many field cannot exist on its own! It must point to a Many2one field that already exists on the other model. Example: One Sale Order has Many Order Lines.

# 'sale.order.line' is the target model. 
# 'order_id' is the Many2one field on that target model that points back here!
order_line_ids = fields.One2many('sale.order.line', 'order_id', string='Order Lines')

C. Many2many (fields.Many2many)

This links Many records in one model to Many records in another model. Odoo handles this automatically behind the scenes by creating a hidden "bridge" table in the database. Example: Many books can have Many tags (e.g., a book can be "Sci-Fi" and "Bestseller", and the "Sci-Fi" tag belongs to many books).

# Links to the 'library.tag' model
tag_ids = fields.Many2many('library.tag', string='Tags')


3. Real-World Code Example

Let's put it all together by creating a simple Library Book model that uses both basic and relational fields:

from odoo import models, fields

class LibraryBook(models.Model):
_name = 'library.book'
_description = 'Library Book'

# Basic Fields
name = fields.Char(string='Title', required=True)
pages = fields.Integer(string='Number of Pages')
publish_date = fields.Date(string='Published On')
is_borrowed = fields.Boolean(string='Currently Borrowed', default=False)

# Relational Fields
# Many books can be written by one author (res.partner)
author_id = fields.Many2one('res.partner', string='Author', required=True)
# Many books can belong to one publisher (res.partner)
publisher_id = fields.Many2one('res.partner', string='Publisher')

# Many books can have Many tags
tag_ids = fields.Many2many('library.book.tag', string='Tags')


💡 Developer Advice for Odoo 19

  1. Name Relational Fields Correctly: This is a strict Odoo convention!

    • Many2one fields should always end in _id (e.g., customer_id, product_id).

    • One2many and Many2many fields contain multiple records, so they should always end in _ids (e.g., line_ids, tag_ids).

  2. The ondelete Attribute: When you create a Many2one field, always think about what should happen if the linked record is deleted. Use ondelete='set null' (the default, empties the field) or ondelete='cascade' (deletes this record too) or ondelete='restrict' (prevents deletion of the parent record).

  3. One2many is Virtual: Did you know that a One2many field does not actually create a column in your PostgreSQL database? It is just a "virtual" shortcut Odoo uses to fetch the reverse of a Many2one relationship quickly!

Rating
0 0

There are no comments for now.

to be the first to leave a comment.