What I need
If the user clicks on my button, take him to different views of different models depending on a field of the current record.
What I did
I have declared a type object button to call a Python method. Inside it, I check the field. If its value is A, I redirect him to the model X and if its value is B, I redirect him to the model Y.
The code
@api.multi
def my_button_method(self):
self.ensure_one()
if self.my_field == 'A':
action_id = self.env.ref(
'my_module.my_ir_actions_act_window_A')
return action_id.__dict__
elif self.my_field == 'B':
action_id = self.env.ref(
'my_module.my_ir_actions_act_window_B')
else:
action_id = False
if action_id:
return action_id.__dict__
If I write this after the definition of action_id
:
_logger.info(action_id.name)
_logger.info(action_id.type)
_logger.info(action_id.res_model)
_logger.info(action_id.view_type)
_logger.info(action_id.view_mode)
_logger.info(action_id.search_view_id)
_logger.info(action_id.help)
I get the right values. So, after googling I saw that __dict__
gives you a dictionary whose keys are the attributes of the object and whose values the values of those attributes.
But the code is giving an error because action_id.__dict__
doesn't return a dictionary with the expected attributes of the action and its values, but the following instead:
{
'_prefetch': defaultdict(
<type 'set'>,
{
'ir.actions.act_window': set([449])
}
),
'env': <odoo.api.Environment object at 0x7f0aa7ed7cd0>,
'_ids': (449,)
}
Can anyone tell me why? I'm trying to avoid this code:
@api.multi
def my_button_method(self):
self.ensure_one()
if self.my_field == 'A':
action_id = self.env.ref(
'my_module.my_ir_actions_act_window_A')
elif self.my_field == 'B':
action_id = self.env.ref(
'my_module.my_ir_actions_act_window_B')
else:
action_id
if action_id:
return {
'name': action_id.name,
'type': action_id.type,
'res_model': action_id.res_model,
'view_type': action_id.view_type,
'view_mode': action_id.view_mode,
'search_view_id': action_id.search_view_id,
'help': action_id.help,
}
May be there is a much better solution using a server action, if so, does anyone know how?
You can do the really short "style":
action = self.env.ref("my_module.my_ir_actions_act_window_A").read()[0]
return action
You will find a lot of examples this "style" around in Odoo code.
Edit: that should also work in Odoo 7-14
Edit: for newer versions for example Odoo 15+ you can also use the following:
action = self.env["ir.actions.actions"]._for_xml_id(
"my_module.my_ir_actions_act_window_A"
)
return action