In Odoo 18, developers often come across advanced framework concepts that streamline the development process. One such powerful concept is the Wrapper Function by using which we can encapsulate, use and modify existing Odoo behaviors in a neat, maintainable fashion.
In this blog, we will look at what a wrapper class is, when and why you should use one, and how developers and teams offering Odoo consulting services can follow best practices when working with wrapper classes in Odoo 18.
What is a Wrapper Function in Odoo?
A Wrapper Function in Odoo serves as a facade that envelops the current model, method or function to provide additional or altered behavior without the need to change the original code.
- They are typically utilized when we want to:
- Enhance existing business functionality in an organized and reusable way.
- Provide validation or logging around existing method.
- Change the order of functionality of the method calls, without having to completely overhaul the original function.
Think of a wrapper more simply, as a decorator pattern applied to Odoo models - a method to "decorate" your function with extra functionality.
Why Use a Wrapper Function?
- Odoo is built as a modular system and encourages extension. However, there can be reasons overriding methods directly can lead to: Code duplication. Conflicts on upgrades to modules. Difficulties debugging.
A Wrapper Function will let developers keep code clean and easy to maintain. Add new functionality, without changing the core. Ensure compatibility with upgrades.
As an example, instead of overriding the write () method on the res.partner model, all write operations can be logged extensible by wrapping the existing write () method.
Example: Creating a Wrapper Function in Odoo 18
from odoo import models, api
class PartnerWrapper(models.AbstractModel):
_name = 'partner.wrapper'
_description = 'Wrapper for Partner Model'
@api.model
def wrap_write(self, original_write):
"""Wrapper for logging and extending write() functionality."""
def wrapped_write(records, vals):
for rec in records:
_logger.info(f"[Wrapper] Updating Partner ID {rec.id} with values {vals}")
# Add pre-processing logic here
result = original_write(records, vals)
# Add post-processing logic here
_logger.info(f"[Wrapper] Successfully updated Partner ID(s): {[r.id for r in records]}")
return result
return wrapped_write
Now, integrate this wrapper into the original model:
import logging
from odoo import models
_logger = logging.getLogger(__name__)
class ResPartner(models.Model):
_inherit = 'res.partner'
# Applying the wrapper to the original write method
def write(self, vals):
wrapper = self.env['partner.wrapper']
wrapped_write = wrapper.wrap_write(super(ResPartner, self).write)
return wrapped_write(self, vals)
Output Behavior:
- Before the write operation → logs the changes to be applied.
- After the write operation → Indicate that this was successful.
- That way you can add logic around existing methods on the fly, without completely overwriting them.
Common Use Cases
Here are some of the use cases in real time where Wrapper Classes are very useful:
Use Case | Description |
Logging | Log before and after CRUD operations without cluttering our core code. |
Performance Tracking | Measure time, before and after, for any of our important methods. |
Validation Layer | Create validations prior to saving or removing records without redeveloping the core logic. |
Third-Party API Integration | Encapsulate calls to other APIs to include error handling and retry behavior. |
Auditing | Record contextual information at method execution (i.e., user, date/time, record data). |
Best Practices
- Use Abstract Models: Always use models to define your wrappers as abstract models to reuse code across models.
- Avoid: Don’t wrap the same method multiple times because this will cause performance issues or unexpected recursion.
- Keep Wrapper Logic Light: If you would like your main path to run quickly, avoid heavy operations inside wrappers. Use light wrappers - just "validations", "logs", or "checks".
- Log Clearly: Always log activity for wrapper actions - this is helpful for debugging and determining traceability.
- Upgrade Compatibility and Safety: Utilizing wrappers will extend existing logic without removing existing logic. Wrappers should have no hard coded core logic or functional business meaning.
Wrapper Class vs Method Override
Aspect | Wrapper Function | Method Override |
Purpose | Add behavior around existing logic | Replace or adjust method logic |
Code Maintenance | Cleaner and modular | Could cause code conflicts |
Reusability | Can apply to multiple models | Typically limited to one model |
Upgrade Safety | High (no modification to core) | Medium to low (depends on depth of override) |
Conclusion
Putting it together, Wrapper Function in Odoo 18 provides a way to extend current logic while keeping your custom solutions modular, clean, and upgrade-safe. Whatever logging, validation, or post-processing hooks you add, wrappers give you peace of mind by providing maintainable code that scales easily, just how professional Odoo development should be.
FAQ
1. What is a Wrapper Class?
A Wrapper Class is essentially a container around an existing method or model, to implement some new functionality, be it logging or some form of validation, without altering the original logic of the code. It is a clean and safe approach to extending the behaviors of Odoo.
2. When should I use a Wrapper Function?
Use a wrapper when you want to:
- Implement logging or validation.
- Measure performance or handle exceptions.
- Extend existing functionality without breaking the original code.
- If you only need to completely change the method of logic, then it probably makes much more sense to override it.
3. Can I use one Wrapper Function across multiple models?
Yes! If you declare your wrapper as an Abstract Model, you can reuse the wrapper across multiple models. This is one of the primary benefits of a wrapper - it helps eliminate duplicate code.
4. Will using too many wrappers slow down my system?
Not if used correctly. Wrappers should contain light logic like small checks, logs, or quick conditions. Avoid putting heavy processing or multiple nested wrappers, and your system will stay fast.
5. Can API integrations utilize Wrapper Function?
Yes, they can. Wrapper classes are perfect for managing API calls, retries and error handling all while keeping your primary logic clean and separated.