Odoo One2many fields represent a fundamental concept in backend development that every developer must understand. When building complex business applications with Odoo, mastering One2many relationships becomes essential for creating efficient data structures. This comprehensive tutorial explores how to implement and optimize One2many fields in your Odoo modules, providing practical examples and best practices for backend developers.
Master Backend Development Guide
Understanding One2many Relationships in Odoo
One2many fields create powerful connections between models in Odoo’s ORM system. Unlike Many2one fields that link multiple records to a single record, One2many fields establish reverse relationships. For instance, while multiple books can have one author (Many2one), one author can have multiple books (One2many).
Core Concepts of Odoo Relational Fields
Before diving into implementation, let’s understand how One2many fields work internally. These fields don’t create database columns; instead, they generate virtual views that display related records through existing Many2one relationships. The ORM constructs these relationships in memory during runtime, making queries to retrieve associated records dynamically.
Setting Up Your Odoo Backend Development Environment
To implement One2many fields effectively, you need a properly configured development environment. Start by creating two related models that demonstrate the relationship clearly.
from odoo import models, fields
class LibraryAuthor(models.Model):
_name = 'library.author'
_description = 'Library Author'
name = fields.Char(string='Author Name', required=True)
book_ids = fields.One2many('library.book', 'author_id', string='Books')
class LibraryBook(models.Model):
_name = 'library.book'
_description = 'Library Book'
name = fields.Char(string='Book Title', required=True)
isbn = fields.Char(string='ISBN')
author_id = fields.Many2one('library.author', string='Author')
Essential Parameters for One2many Fields
When defining One2many fields, three parameters prove crucial for proper functionality:
- Comodel Name: Specifies which model to connect (e.g., ‘library.book’)
- Inverse Name: Identifies the Many2one field in the related model (e.g., ‘author_id’)
- String: Provides the field label for user interfaces
Implementing Odoo One2many Fields Step by Step
Let’s walk through creating a complete One2many relationship between authors and books. This practical example demonstrates real-world implementation patterns.
Step 1: Define the Parent Model
First, create the author model with the One2many field:
class LibraryAuthor(models.Model):
_name = 'library.author'
_description = 'Library Author'
name = fields.Char(string='Author Name', required=True)
biography = fields.Text(string='Biography')
book_ids = fields.One2many(
comodel_name='library.book',
inverse_name='author_id',
string='Published Books',
copy=False
)
Step 2: Create the Child Model
Next, implement the book model with the corresponding Many2one field:
class LibraryBook(models.Model):
_name = 'library.book'
_description = 'Library Book'
name = fields.Char(string='Book Title', required=True)
isbn = fields.Char(string='ISBN', size=13)
publication_date = fields.Date(string='Publication Date')
author_id = fields.Many2one(
comodel_name='library.author',
string='Author',
ondelete='cascade'
)
Step 3: Configure Views for One2many Display
Create form views that properly display One2many relationships:
<record id="view_library_author_form" model="ir.ui.view">
<field name="name">library.author.form</field>
<field name="model">library.author</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="name"/>
<field name="biography"/>
</group>
<notebook>
<page string="Books">
<field name="book_ids">
<tree editable="bottom">
<field name="name"/>
<field name="isbn"/>
<field name="publication_date"/>
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
Advanced Techniques for Odoo Relational Fields
Domain Filtering in One2many Fields
Apply domain filters to restrict which records appear in One2many fields:
published_book_ids = fields.One2many(
'library.book',
'author_id',
string='Published Books',
domain=[('state', '=', 'published')]
)
Context Passing for Default Values
Use context to set default values when creating records through One2many fields:
book_ids = fields.One2many(
'library.book',
'author_id',
string='Books',
context={'default_state': 'draft'}
)
Computed One2many Fields
Create dynamic One2many fields using compute methods:
recent_book_ids = fields.One2many(
'library.book',
'author_id',
string='Recent Books',
compute='_compute_recent_books'
)
def _compute_recent_books(self):
for author in self:
recent_date = fields.Date.today() - timedelta(days=365)
author.recent_book_ids = author.book_ids.filtered(
lambda b: b.publication_date >= recent_date
)
Best Practices for Odoo Backend Development
Naming Conventions
Follow Odoo’s naming conventions consistently:
- Use plural forms for One2many fields (book_ids, not book_id)
- Use singular forms for Many2one fields (author_id, not authors_id)
- Include ‘_ids’ suffix for One2many fields
Performance Optimization
Optimize One2many field performance with these strategies:
- Limit Field Loading: Specify which fields to load in tree views
- Use Pagination: Implement pagination for large datasets
- Lazy Loading: Load related records only when needed
book_ids = fields.One2many(
'library.book',
'author_id',
string='Books',
limit=100
)
Security Considerations
Implement proper access controls for One2many relationships:
<record id="library_book_rule" model="ir.rule">
<field name="name">Library Book Access</field>
<field name="model_id" ref="model_library_book"/>
<field name="domain_force">[('author_id.user_id', '=', user.id)]</field>
</record>
Common Pitfalls and Solutions
Avoiding Circular Dependencies
Prevent circular dependencies when models reference each other:
Avoid this pattern
class ModelA(models.Model):
_name = 'model.a'
b_ids = fields.One2many('model.b', 'a_id')
class ModelB(models.Model):
_name = 'model.b'
a_id = fields.Many2one('model.a')
a_ids = fields.One2many('model.a', 'b_id') # Circular reference
Handling Deletion Cascades
Configure appropriate deletion behaviors:
author_id = fields.Many2one(
'library.author',
string='Author',
ondelete='restrict' # Options: cascade, restrict, set null
)
Managing Large Datasets
Implement strategies for handling large One2many collections:
@api.model
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None):
# Override to implement custom pagination
if 'book_ids' in (fields or []):
# Implement custom loading logic
pass
return super().search_read(domain, fields, offset, limit, order)
Testing One2many Relationships
Create comprehensive tests for your One2many implementations:
class TestLibraryRelations(TransactionCase):
def setUp(self):
super().setUp()
self.Author = self.env['library.author']
self.Book = self.env['library.book']
def test_one2many_creation(self):
author = self.Author.create({
'name': 'Test Author',
'book_ids': [(0, 0, {
'name': 'Test Book 1',
'isbn': '1234567890123'
}), (0, 0, {
'name': 'Test Book 2',
'isbn': '9876543210987'
})]
})
self.assertEqual(len(author.book_ids), 2)
self.assertEqual(author.book_ids[0].author_id, author)
Integration with Other Odoo Features
Workflow Integration
Integrate One2many fields with Odoo workflows:
@api.depends('book_ids.state')
def _compute_all_books_published(self):
for author in self:
author.all_books_published = all(
book.state == 'published' for book in author.book_ids
)
Report Generation
Use One2many data in reports effectively:
<t t-foreach="author.book_ids" t-as="book">
<tr>
<td><t t-esc="book.name"/></td>
<td><t t-esc="book.isbn"/></td>
<td><t t-esc="book.publication_date"/></td>
</tr>
</t>
Conclusion
Mastering Odoo One2many fields opens doors to building sophisticated backend applications. By understanding the relationship between One2many and Many2one fields, following naming conventions, and implementing performance optimizations, you create maintainable and efficient Odoo modules. Remember that One2many fields provide virtual representations of relationships, making them powerful tools for data modeling in your Odoo backend development projects.
For more advanced Odoo development techniques, explore the official Odoo documentation and join the vibrant Odoo Community to connect with fellow developers and share experiences.
Discover more from teguhteja.id
Subscribe to get the latest posts sent to your email.


Pingback: One2many view filter: Ultimate 7-Step Guide to Dynamic Odoo Success