When it comes to tailoring your Odoo application to meet the specific needs of your business, understanding how to override the core ORM (Object Relational Mapping) methods is essential. Odoo 18, the latest version of the popular open-source ERP platform, offers even more flexibility and performance improvements—making it a powerful ERP for Small Companies and enterprises alike.
Whether you’re an Odoo developer, a business owner with a tech-savvy mindset, or an ERP consultant looking to fine-tune business logic, this guide walks you through how to override the create, write, and unlink methods in Odoo 18 with best practices and practical examples.
? Why Override Core Methods in Odoo?
Odoo’s standard behavior is often sufficient for most use cases. But business requirements aren't always standard. You might want to:
- Automatically populate fields on creation.
- Add validations before a record is saved.
- Log changes when records are updated.
- Restrict deletions or perform cleanup actions before deleting data.
That’s where overriding comes into play. Let’s dive into the basics.
? Preliminaries: Where Do These Methods Belong?
In Odoo, you override methods inside a model class that inherits from models.Model. The three primary ORM methods are:
- create(self, vals)
- write(self, vals)
- unlink(self)
These methods are defined in models (typically found in files like models.py or split across several model files).
?️ How to Override the create() Method in Odoo 18
The create() method is triggered when a new record is created via the ORM.
✅ Syntax:
python
@api.model
def create(self, vals):
# your custom logic here
return super(YourModel, self).create(vals)
? Example:
Let’s say we want to automatically generate a sequence number for a custom model school.student when a new student record is created.
python
from odoo import models, fields, api
class Student(models.Model):
_name = 'school.student'
_description = 'Student'
name = fields.Char(string='Name')
student_id = fields.Char(string='Student ID', readonly=True)
@api.model
def create(self, vals):
if vals.get('student_id', 'New') == 'New':
vals['student_id'] = self.env['ir.sequence'].next_by_code('school.student') or 'New'
return super(Student, self).create(vals)
? Pro Tip:
Always call super() after your custom logic to avoid breaking core functionalities.
✍️ Overriding the write() Method in Odoo 18
The write() method is used to update existing records.
✅ Syntax:
python
def write(self, vals):
# your custom logic here
return super(YourModel, self).write(vals)
? Example:
Let’s log a message whenever a student’s name is updated.
python
def write(self, vals):
for record in self:
if 'name' in vals:
old_name = record.name
new_name = vals.get('name')
_logger.info(f"Student name changed from {old_name} to {new_name}")
return super(Student, self).write(vals)
? Pro Tip:
Avoid heavy computations in write() as it can affect performance when updating multiple records.
❌ How to Override the unlink() Method in Odoo 18
The unlink() method is triggered when a record is deleted. This is your last chance to perform cleanup actions.
✅ Syntax:
python
def unlink(self):
# your custom logic here
return super(YourModel, self).unlink()
? Example:
Prevent deletion of a student record if they are enrolled in any course.
python
def unlink(self):
for student in self:
if student.course_ids:
raise UserError("You cannot delete a student who is enrolled in a course.")
return super(Student, self).unlink()
? Pro Tip:
Be cautious—overriding unlink() incorrectly can prevent necessary data deletion or lead to orphaned records.
?️ Security & Access Rights Considerations
Even if you override these methods with validations and checks, remember:
- They do not override the access rights and record rules defined in Odoo.
- You still need to define proper ACLs (Access Control Lists) and Record Rules in XML.
If a user lacks permission to delete or update a record, your overridden method will never be reached.
? Testing Your Overrides
Always test your overridden methods using:
- Odoo’s built-in unit testing with @odoo.tests.common.TransactionCase.
- Manual testing through the UI or Postman if using Odoo's REST API.
- Logging (_logger.info()) or print() statements during development (remove before deploying).
? Best Practices for Overriding Methods
- Use super(): Always call the parent method unless you have a very good reason not to.
- Avoid Hardcoding: Use self.env['model.name'] and configurations for flexibility.
- Error Handling: Use raise UserError() to display clean error messages to users.
- Performance Awareness: Be cautious when applying logic to bulk operations.
? Common Mistakes to Avoid
Mistake | Why It’s Problematic |
Forgetting super() | Breaks standard behavior |
Heavy logic in write() | Slows down updates |
Raising generic exceptions | Poor UX and debugging difficulty |
Skipping security checks | Vulnerable to unauthorized actions |
? Real-Life Use Cases of Overriding in Business
- Auto-generating Customer Codes: On create() in res.partner.
- Tracking Payment Changes: On write() in account.payment.
- Blocking Deletion of Key Records: On unlink() in product.product.
By leveraging these overrides, companies can enforce data integrity, automate repetitive tasks, and enhance workflow efficiency.
✅ Conclusion
Overriding the create, write, and unlink methods in Odoo 18 allows you to inject powerful custom behavior at the core level of your ERP application. While it opens up significant possibilities, it also comes with responsibilities—like maintaining performance and data integrity.
If you’re looking to customize your Odoo system but want to ensure it’s done the right way, hire an expert Odoo Implementation Consultant to streamline the process, avoid costly mistakes, and future-proof your business solution.
Need help customizing your Odoo 18 modules?
Let’s chat about your project and take your ERP to the next level!