Welcome, Odoo developers! In the ever-evolving landscape of enterprise resource planning, Odoo stands out with its powerful ORM (Object-Relational Mapping) that allows for highly flexible and customizable solutions. One of the “hidden gems” of Odoo development, as described by experts like Jayank Aghara, is the @api.depends_context decorator. This essential tool allows you to build smarter, more dynamic computed fields that react not just to changes in other record fields, but to changes in the surrounding environment’s context.
This comprehensive Odoo api.depends_context Tutorial will guide you through understanding, implementing, and leveraging this powerful decorator to create truly adaptive Odoo applications, particularly in Odoo 18. We’ll explore its syntax, use cases, and walk you through a practical, step-by-step example.
For a foundational understanding of the concept and its importance, you can refer to insights shared on this LinkedIn post about @api.depends_context by Muhammad El Nayed Mahfouz. Additionally, if you’re exploring other aspects of Odoo 18 development, such as adding different types of fields, you might find this tutorial on adding images in Odoo 18 helpful as a complementary resource.
Let’s dive in and unlock the full potential of context-aware computed fields!
What is @api.depends_context?
At its core, @api.depends_context is a decorator in Odoo that you apply to a compute method for a non-stored field. Its primary purpose is to signal to Odoo’s ORM that the value of the computed field depends on one or more keys present in the self.env.context dictionary.
Think of it this way: while @api.depends() tells Odoo, “Hey, if this field changes, recompute me,” @api.depends_context() says, “Hey, if this value in the environment’s context changes, recompute me.” This distinction is crucial for building applications that respond dynamically to things like user preferences, session settings, or specific operational flags.
Common context keys that often drive such computations include:
'lang': The user’s current language, essential for multi-lingual applications.'tz': The user’s timezone, critical for displaying time-sensitive data accurately.- Custom Context Keys: Any arbitrary key-value pair you pass into the context, such as
'show_price','currency','bypass_security', or'report_type'.
This powerful mechanism ensures that your data presentation and logic remain consistent with the active user environment without requiring a manual refresh or a database field change.
Why and When to Use Odoo api.depends_context?
The decision to use @api.depends_context boils down to scenarios where your computed field’s output is inherently tied to contextual information rather than just static record data. Here are the key indicators and use cases for when this powerful decorator becomes indispensable:
- Context-Dependent Output: Your computed field’s value directly relies on a specific value found within
self.env.context. This is the most fundamental reason. - Automatic Recomputation on Context Changes: You need the field to automatically recompute when a relevant context value changes, even if no underlying model fields have been modified. This provides a seamless user experience, especially in dynamic UIs or multi-context environments.
Consider these practical applications where an Odoo api.depends_context Tutorial will guide you to enhance your Odoo solution:
- Language-Specific Fields: Displaying product names, descriptions, or labels translated into the user’s active language. This is perhaps the most common and illustrative use case, and one we’ll tackle in our Odoo api.depends_context Tutorial.
- Context-Based Pricing: Calculating and displaying prices that might vary based on a
'currency'key in the context, a'pricelist_id', or even a'show_tax'flag. Imagine showing different prices in different currencies to different users or for specific reports. - Multi-Currency Computed Values: Aggregating financial data or computing totals that need to be presented in a specific currency determined by the context, rather than the company’s base currency.
- User Role-Based Content Display: Showing or hiding certain information or modifying a computed string based on a custom context key that reflects the user’s role or permissions for a specific operation. For example, an administrator might see a ‘debug_info’ field while a regular user does not.
- Timezone-Aware Displays: Adjusting timestamps or durations in computed fields to reflect the user’s local timezone.
Without @api.depends_context, achieving these dynamic behaviors would involve manual refreshes, complex JavaScript, or less elegant workarounds, none of which provide the clean, ORM-integrated solution that Odoo offers. This is why mastering this part of Odoo development is so beneficial.
Syntax and Important Considerations
The syntax for @api.depends_context is straightforward, making it easy to integrate into your computed field methods.
Basic Syntax:
from odoo import api, fields, models
class MyModel(models.Model):
_name = 'my.model'
my_computed_field = fields.Char(
string="My Dynamic Field",
compute="_compute_my_field"
)
@api.depends_context('lang', 'show_price')
def _compute_my_field(self):
for rec in self:
lang = self.env.context.get('lang', 'en_US')
show_price = self.env.context.get('show_price', False)
# Your computation logic here, using 'lang' and 'show_price'
rec.my_computed_field = f"Lang: {lang}, Price Display: {show_price}"
In this example, _compute_my_field will be re-executed whenever the 'lang' or 'show_price' keys in the environment context change.
Important Notes for Odoo api.depends_context Tutorial:
While incredibly powerful, @api.depends_context comes with a few crucial points to remember:
- Non-Stored Fields Only: This decorator primarily works for non-stored fields (
store=False) or dynamic computations. Stored fields are typically designed to persist their values in the database, and their recomputation is usually tied to database-level changes or@api.dependson stored fields. Context changes are transient and client-side, making them unsuitable for directly triggering recomputations of stored fields. - Backend/Server-Side Context Changes: The recomputation is reliably triggered when the context changes in backend calls or via server-side logic (e.g., when using
with_context()). It’s important to understand that context changes originating directly from the frontend UI (like a user changing their language in the preferences without a full page reload that re-fetches data) do not always auto-trigger the recomputation of a field displayed on the same form. For immediate frontend updates, you might still need client-side code to refresh the view or explicitly call a method. However, for data fetched from the backend (like in list views, reports, or subsequent backend calls), the context changes work perfectly. - Paired with
with_context(): This decorator is commonly paired withrecordset.with_context(...)to explicitly set or simulate specific context values. This is incredibly useful for testing, forcing specific behaviors, or generating reports in a particular context (e.g., a report in French for a German user). For instance,product.with_context(lang='fr_FR').namewill fetch the French translation of the product’s name.
Understanding these considerations is vital for correctly applying the Odoo api.depends_context Tutorial and building robust Odoo features.
The Synergy: Combining @api.depends and Odoo api.depends_context
Often, a computed field’s value might depend on both underlying record fields and the current environment context. Odoo’s ORM elegantly handles this by allowing you to combine both decorators on a single compute method. This creates a powerful and comprehensive dependency management system.
Consider a scenario where a product’s “Localized Label” needs to update if:
- The product’s category changes (a field dependency).
- The user’s language changes (a context dependency).
Here’s how you’d structure such a compute method:
from odoo import api, fields, models
class ProductTemplate(models.Model):
_inherit = 'product.template'
dynamic_label = fields.Char(
string="Dynamic Label",
compute="_compute_dynamic_label"
)
@api.depends('categ_id', 'name') # Reacts to field changes
@api.depends_context('lang', 'show_debug_info') # Reacts to context changes
def _compute_dynamic_label(self):
for rec in self:
lang = self.env.context.get('lang', 'en_US')
show_debug_info = self.env.context.get('show_debug_info', False)
translated_name = rec.with_context(lang=lang).name
category_name = rec.categ_id.display_name if rec.categ_id else "No Category"
label_parts = [f"[{category_name}]", translated_name]
if show_debug_info:
label_parts.append(f"(Context Lang: {lang})")
rec.dynamic_label = " ".join(label_parts)
In this example, the _compute_dynamic_label method will be triggered whenever:
- The
categ_idof theproduct.templaterecord changes. - The
nameof theproduct.templaterecord changes. - The
'lang'key inself.env.contextchanges. - The
'show_debug_info'key inself.env.contextchanges.
This layered approach ensures that your computed field remains accurate and responsive to all relevant data points, whether they are part of the record itself or part of the surrounding execution environment. It’s a testament to the flexibility that Odoo’s ORM offers when you master the Odoo api.depends_context Tutorial.
Step-by-Step Tutorial: Implementing Odoo api.depends_context in Odoo 18
Now, let’s put theory into practice with a hands-on Odoo api.depends_context Tutorial for Odoo 18. We’ll create a computed field named localized_label on the product.template model that combines the product’s category and its name, with the name being automatically translated based on the user’s current language.
Prerequisites:
- An Odoo 18 development environment (e.g., via Docker, a virtual environment, or directly installed).
- Basic familiarity with creating custom Odoo modules and the Odoo ORM.
- Make sure you have at least two languages installed and activated in Odoo (e.g., English and French) to properly test the translation.
Step 1: Create or Setup Your Custom Module
If you don’t have a custom module, create one. For this tutorial, we’ll assume a module named my_localization_module.
my_localization_module/
__init__.py
__manifest__.py
models/
__init__.py
product_template.py
my_localization_module/__manifest__.py:
Ensure your manifest declares a dependency on theproductmodule.{ 'name': 'Product Localization with Context', 'version': '1.0', 'summary': 'Demonstrates @api.depends_context for localized product labels.', 'depends': ['product'], # IMPORTANT: We are extending the product module 'installable': True, 'application': False, 'auto_install': False, 'license': 'LGPL-3', }my_localization_module/__init__.py:
Import yourmodelssubdirectory.from . import modelsmy_localization_module/models/__init__.py:
Import your custom model file.from . import product_template
Step 2: Define the Computed Field with Odoo api.depends_context
Now, create the product_template.py file inside your my_localization_module/models/ directory. This file will contain the core logic for our Odoo api.depends_context Tutorial example.
from odoo import models, api, fields
class ProductTemplate(models.Model):
_inherit = 'product.template'
localized_label = fields.Char(
string="Localized Label",
compute="_compute_localized_label",
store=False # Important: This field should not be stored
)
@api.depends('categ_id')
@api.depends_context('lang')
def _compute_localized_label(self):
"""
Computes the localized label for the product template.
The label combines the category name and the product name,
with the product name translated based on the user's language context.
"""
for rec in self:
# 1. Get the current language from the environment context
# If not explicitly set in context, default to the user's preferred language
current_lang = self.env.context.get('lang') or self.env.user.lang
# 2. Get the translated product name using with_context()
# rec.with_context(lang=current_lang) creates a new recordset
# with the specified language in its context.
# Accessing .name on this new recordset fetches the name
# translated to `current_lang`.
translated_product_name = rec.with_context(lang=current_lang).name
# 3. Get the category name
category_name = rec.categ_id.display_name if rec.categ_id else "Uncategorized"
# 4. Construct the final localized label
rec.localized_label = f"[{category_name}] {translated_product_name}"
Explanation of the Code:
_inherit = 'product.template': This line tells Odoo that we are extending the existingproduct.templatemodel, not creating a new one.localized_label = fields.Char(...): We define a new character field.string="Localized Label": This sets the display name for the field in the Odoo UI.compute="_compute_localized_label": This links our field to the method that will calculate its value.store=False: Crucially, this specifies that the field’s value will not be saved in the database. As discussed,@api.depends_contextis best suited for non-stored fields.
@api.depends('categ_id'): This decorator ensures that if the product’s category (categ_id) is changed, the_compute_localized_labelmethod will be re-executed to update thelocalized_label.@api.depends_context('lang'): This is the core of our Odoo api.depends_context Tutorial. It declares that the_compute_localized_labelmethod depends on the'lang'key in the environment context. If the user’s active language changes (e.g., viaself.env.contextbeing modified or awith_context()call), this method will be triggered to recompute the field._compute_localized_label(self): This method contains the logic for calculating the field’s value for eachproduct.templaterecord in theselfrecordset.current_lang = self.env.context.get('lang') or self.env.user.lang: This line safely retrieves the language. It first tries to get the'lang'from the current environment context (self.env.context). If it’s not present (which can happen), it falls back to the language configured for the current user (self.env.user.lang).translated_product_name = rec.with_context(lang=current_lang).name: This is where the magic happens!rec.with_context(lang=current_lang): Creates a new recordset based onrec, but with thelangkey in its context explicitly set tocurrent_lang..name: When you access a translatable field (likenameonproduct.template) on a recordset with a specificlangin its context, Odoo automatically retrieves the translation for that language.
category_name = rec.categ_id.display_name if rec.categ_id else "Uncategorized": This retrieves the display name of the associated product category. If there’s no category, it defaults to “Uncategorized.”rec.localized_label = f"[{category_name}] {translated_product_name}": Finally, thelocalized_labelfor the current record (rec) is set by formatting the category and the translated product name into a single string.
Step 3: Install or Upgrade Your Module
- Restart your Odoo server to ensure it detects the new module files.
- Log in to Odoo as an administrator.
- Go to the “Apps” menu.
- Search for “Product Localization with Context” (or the name you gave your module).
- Click “Install”. If you’ve previously installed it, click “Upgrade”.
Step 4: Test the Functionality
To observe the power of this Odoo api.depends_context Tutorial, follow these steps:
- Configure Translations:
- Go to “Settings” -> “Translations” -> “Load a Translation”.
- Select “French” (or another language you prefer) and click “Load”.
- Now, translate a few product names. Go to “Sales” -> “Products” -> “Products”. Open any product. In the product form, hover over the
Product Namefield and click the little translation icon (a globe) that appears. Enter a French translation for the product name and save. Do this for 2-3 products.
- Observe the Field:
- Go back to “Sales” -> “Products” -> “Products”.
- Open one of the products you translated. You should see the “Localized Label” field displaying the category and the product name in the current user’s language (likely English initially).
- Change User Language and Re-Test:
- Click on your user name in the top right corner of Odoo and select “Preferences”.
- Change your “Language” to “French (fr_FR)”. Click “Save”.
- Now, navigate back to “Sales” -> “Products” -> “Products”.
- Open the same product. You should immediately see the “Localized Label” field update! The product name part of the label will now be in French, demonstrating that the
@api.depends_context('lang')decorator has successfully triggered a recomputation based on the context change. - Change the language back to English, and you’ll see it revert.
This hands-on exercise clearly illustrates the dynamic nature of localized_label thanks to our Odoo api.depends_context Tutorial.
Beyond the Example: Advanced Tips and Best Practices
While our example focused on the lang context key, the true power of @api.depends_context extends to any custom context key you define. Here are some advanced tips and best practices to maximize your learning from this Odoo api.depends_context Tutorial:
- Custom Context Keys for Business Logic:
You can pass custom keys viawith_context()in your Python code, or even in XML views using context attributes (<field name="my_field" context="{'my_custom_key': True}"/>). This allows you to create fields whose behavior changes dramatically based on flags like'is_report_mode','show_detailed_view', or'target_currency'.# Example using a custom context key class SaleOrderLine(models.Model): _inherit = 'sale.order.line' display_amount = fields.Float( string="Display Amount", compute="_compute_display_amount", store=False ) @api.depends('price_subtotal') @api.depends_context('show_tax_inclusive') def _compute_display_amount(self): for rec in self: show_tax_inclusive = self.env.context.get('show_tax_inclusive', False) if show_tax_inclusive: rec.display_amount = rec.price_total # Assuming price_total includes tax else: rec.display_amount = rec.price_subtotalThis
display_amountwould dynamically show either the tax-exclusive or tax-inclusive amount based on theshow_tax_inclusivecontext key. - Performance Considerations:
While powerful,@api.depends_contextshould be used judiciously. If a computed field involves complex calculations and its context keys change very frequently, it could impact performance. For most standard use cases, Odoo’s ORM is highly optimized, but it’s always good to be mindful. Ensure your compute methods are efficient. - Debugging
depends_contextIssues:
If your field isn’t recomputing as expected, check the following:- Is the field
store=False? - Are you sure the context key you’re depending on is actually changing in
self.env.contextwhen the recomputation is expected? Use_logger.info(self.env.context)within your compute method to print the context and verify its contents. - Are you testing primarily in backend scenarios or with
with_context()calls, where context changes are reliably picked up?
- Is the field
- Integration with Odoo’s Core Modules:
Many core Odoo modules leverage context-based logic. Understanding thisOdoo api.depends_context Tutorialwill help you debug and extend functionalities in areas like multi-company, multi-currency, and translation features, allowing for deeper customization and more robust solutions.
By understanding these advanced aspects, you can move beyond basic implementation and truly master context-aware computing in Odoo development.
Conclusion
The @api.depends_context decorator is an incredibly versatile and powerful tool in the Odoo developer’s arsenal. By allowing computed fields to react to environmental context changes, it empowers you to build highly dynamic, adaptive, and user-centric applications. From language-aware labels to context-based pricing and role-specific data displays, the possibilities are vast.
Through this comprehensive Odoo api.depends_context Tutorial, you’ve learned:
- What
@api.depends_contextis and how it differs from@api.depends. - When and why to employ this decorator for context-sensitive computed fields.
- Its essential syntax and important considerations, such as its application to non-stored fields.
- How to combine it effectively with
@api.dependsfor robust dependency management. - A practical, step-by-step example for implementing a localized product label in Odoo 18.
By incorporating the principles from this guide, you can unlock a new level of sophistication in your Odoo customizations, making your applications more responsive and user-friendly. Don’t hesitate to experiment with different context keys and scenarios. The more you practice, the more intuitive this powerful feature will become.
What are your favorite use cases for @api.depends_context? Share your experiences in the comments below!
Discover more from teguhteja.id
Subscribe to get the latest posts sent to your email.

