Hi guys,
In this tutorial I will learn you how to create buttons in views. The form buttons are always shown at the top of the form and are very handy to perform actions on your current record. After this tutorial you can create your own buttons and actions behind the buttons.
1. Creating your model and fields
The first step that you need to do is to create a model and add the fields you need. In my example I will just create a simple form with two fields named ‘name’ and ‘password’. So my model looks like this:
1 2 3 4 5 6 7 |
# -*- coding: utf-8 -*- from openerp import models, fields, api class button_action_demo(models.Model): _name = 'button.demo' name = fields.Char(required=True,default='Click on generate name!') password = fields.Char() |
This creates a new model in the database named ‘button.demo’ and will contain two custom added fields: ‘name’ and ‘password’. The field ‘name’ will be a required field and by default it will contain the text ‘Click on generate name!’)
2. Creating the view with buttons
After the model fields have been made it is time to create your view. For this example I will create a simple form view that shows these two fields and I will add three buttons:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<record model="ir.ui.view" id="view_buttons_form"> <field name="name">Buttons</field> <field name="model">button.demo</field> <field name="type">form</field> <field name="arch" type="xml"> <form string="Button record"> <!--The header tag is built to add buttons within. This puts them at the top --> <header> <!--The oe_highlight class gives the button a red color when it is saved. It is usually used to indicate the expected behaviour. --> <button string="Generate name" type="object" name="generate_record_name" class="oe_highlight"/> <button string="Generate password" type="object" name="generate_record_password"/> <button string="Clear data" type="object" name="clear_record_data"/> </header> <group> <field name="name"/> <field name="password"/> </group> </form> </field> </record> |
Which will look like this:
So, how exactly does Odoo know that the buttons need to be at the top of the form? Because of the header tag! Everything within this tag will be shown at the top of your form. So, this creates three buttons, but how do we trigger an action from this button? Have a closer look at the code for one of those buttons:
1 |
<button string="Generate name" type="object" name="generate_record_name" class="oe_highlight"/> |
Noticing anything? The type=”object” is telling us that we have an object and the name=”generate_record_name” is a link to a Python function. When the user clicks on the button “Generate name” Odoo will trigger the Python function ‘generate_record_name’ and from there on we can do whatever we want. So let us create the actions for the buttons!
3. Creating actions behind the buttons
Now that the view is built and we gave all buttons a name that makes the Python go off we should create the Python functions! Lets first create one for the ‘generate_record_name’ button:
1 2 3 4 |
@api.one def generate_record_name(self): #Generates a random name between 9 and 15 characters long and writes it to the record. self.write({'name': ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(randint(9,15)))}) |
self is defining the current record, so this means we can access anything from that record and modify it. The self.write will update the values for this record in the database. By saying ‘name’: we are telling to update the field ‘name’ in the view. In this example I created a simple function that generates a random name between 9 and 15 characters long.
Tip: @api.one is used for one record and cannot be used for multiple records. If you’d want this you would need @api.multi.
If you would now click on the button a name would be generated from this function and would be shown directly on the view.
Now create the second function ‘generate_record_password’ for the button “Generate password”:
1 2 3 4 |
@api.one def generate_record_password(self): #Generates a random password between 12 and 15 characters long and writes it to the record. self.write({'password': ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(randint(12,15)))}) |
This function does almost the same as the previous but it will generate a password between 12 and 15 characters and write it on the field ‘password’ in place of ‘name’.
Next, lets create our third function ‘clear_record_data’ for the button ‘Clear data’. This function will clear all data from the fields:
1 2 3 4 5 6 |
@api.one def clear_record_data(self): self.write({ 'name': '', password': '' }) |
That is all! You can now create buttons with actions and perform changes on the fields.
4. Conclusion
Buttons are very handy in Odoo and can do just about anything. It is easy to perform actions for the user, change fields, show new views, …
Tip: You can also use buttons in combination with attrs and flows to make them even more useful! You can find this tutorial here.
Do you want to try a demo module and see the source code of this tutorial? You can view on my Github account. Has this tutorial helped you, do you have any feedback or questions? Post away!
Hi Christian,
Thanks a lot! Just create a button with an action behind it (see https://www.odoo.com/nl_NL/forum/help-1/question/how-to-open-a-form-from-a-view-button-37937 for example). Showing the button only when an invoice is invoiced can be done with attrs. An example: https://www.odoo.com/nl_NL/forum/help-1/question/attrs-invisible-with-more-than-2-arguments-or-with-10457
How do i create a button that creates a task when i click on that button
Thank you for the tutorial, it’s very helpful. if i want to show another view by clicking on a button, what shall i put on the function that will be triggered ? and how can i specify that a view is modal ?
Hi Othman,
You’re welcome! There are quite some cases for this. Actions from the Python code, smart buttons, normal buttons, … have a look at the documentation. You can find an example action here: https://www.odoo.com/forum/help-1/question/how-to-open-a-new-form-when-i-click-in-a-button-66751
Hello Yenthe, really useful your blog, congrats!!
I have a question, sorry if here is not the best place.
I want to save or discard data from a form (odoo v8), but before, I want to raise a pop-up asking.
Example.
Customer form / name field
I change the name field, and when I press save, It raises a pop-up asking: Are you sure you want to change the name?
And I will have two buttons
Accept (It saves the new changes)
Cancel (It discards the changes).
I know how to make the pop-up but my problem is in the buttons. Do you know how can I implement this in odoo? Or maybe you know any module with this functionallity so I can replicate.
Thanks in advance!
Javier García
Hi Javier,
Thanks! Happy to hear you find it usefull. The default behaviour would be with a Warning. If you really want to add in a dialog with two buttons and actions you should create a wizard / dialog which you trigger on the function of saving or updating the record.
Thanks Yenthe, keep up the good work!!
Cheers
More than welcome and thanks, I try to!
Hello Yenthe, nice tutorial, thank you for sharing the knowledge.
Is there a way how to update the fields content without writing to the database (button triggered onchange-like behaviour)?
I have a transition model with several fields that should be updated on a button press (getting data from external source) while other fields are to be filled by user after this action. The problem is that the fields filled by user are required so Odoo cannot write the record because of constraints. I also cannot pass the data in the context when creating a view, because the button should update data from external source only on demand. Is there a way to do this?
Hi Mimmon,
More than welcome! Why not use a simple function behind the button that updates the values the moment you click on the button? You can simply call a Python function from the button, do calls to your remote database (XML-RPC) and then fill up the fields you’d like in your current Odoo.
Nice tutorials:) I bet you get a lot of traffic and customers through your tutorials. This is not the first tutorial of yours I ran into!!! Nice done, generating so much content!!!! Very good move! I hope you get a lot of Odoo 9 enquiries Yenthe!
I wish you all the best and thank you for your great content!
Malte
Hi Malte,
Thanks a lot for the very positive feedback 🙂 I don’t make any profit on my tutorials, the profit that I make with the adverts is used to pay the hosting, that’s it. I’m just trying to help as many people as I can to get up to speed with Odoo.
Thank you so much Yenthe 🙂 , your tutorials helped me a lot !!.
– Sahil Taneja
Happy to hear they’re helping, you’re welcome!
Hello Yenthe,
1º) Thank you for your tutorials about buttons and create funct.
2º) I try to create a button in view form in a custom module. The button when click try to create new record based in the filled form (if I can do the next step I will try to change date field in the next phase) but Odoo v8 raise this error:
TypeError: cannot convert dictionary update sequence element #0 to a sequence
This is the code put in pastebin:
https://pastebin.com/8SdWaE2S
Thank you for your time and kind regards,
Marco García Baturan
Hi Marco,
You’re welcome!
Why do you pass all keys like this record[‘val1’, ‘val2’]? You should do record.val1 = True
record.val2 = True etc.