Hi,
To implement chained selection fields in Odoo where one field depends on another, you can use @api.onchange to trigger API calls when a field changes. For example, selecting a Category can fetch Subcategories from an external API, and selecting a Subcategory can fetch Items.
It’s recommended to store the entire API response in a JSON or Text field, so you can reuse it later for reporting or audits. Dynamic options for dependent fields can be populated at runtime using the API response.
For best practices, avoid using API calls in computed fields, consider caching if API performance is an issue, and use Many2one fields with dynamic domains for larger datasets. Alternatively, syncing API data periodically into Odoo models can improve performance and maintain relational integrity.
Sample Code:-
category = fields.Selection([], string="Category")
subcategory = fields.Selection([], string="Subcategory")
item = fields.Selection([], string="Item")
# Optional JSON fields to store API responses
category_data = fields.Text(string="Category Data")
subcategory_data = fields.Text(string="Subcategory Data")
item_data = fields.Text(string="Item Data")
@api.model
def get_category_selection(self):
# Fetch from API
response = requests.get("https://api.example.com/categories")
if response.status_code == 200:
data = response.json()
# Save complete data for audit
self.category_data = json.dumps(data)
# Return selection list as tuples
return [(d['id'], d['name']) for d in data]
return []
@api.onchange('category')
def _onchange_category(self):
if self.category:
response = requests.get(f"https://api.example.com/categories/{self.category}/subcategories")
if response.status_code == 200:
data = response.json()
self.subcategory_data = json.dumps(data)
return {
'domain': {},
'value': {'subcategory': False},
'options': {'subcategory': [(d['id'], d['name']) for d in data]},
}
@api.onchange('subcategory')
def _onchange_subcategory(self):
if self.subcategory:
response = requests.get(f"https://api.example.com/subcategories/{self.subcategory}/items")
if response.status_code == 200:
data = response.json()
self.item_data = json.dumps(data)
return {
'domain': {},
'value': {'item': False},
'options': {'item': [(d['id'], d['name']) for d in data]},
}
Hope it helps