In this tutorial I will learn you how to create a handle widget. A handle widget gives you the option to re-order lines in a many2many, making records drag and droppable. This is a very hand feature to order items and eventually change the order on reports for example.
An example from before re-arranging a many2many and after:
1. Creating the model and fields
For a drag and drop (handle) widget you will need a many2many and for having a many2many you need to create a link to another table. The first step is to create a new table, in case you don’t already have one, or otherwise you can skip to part 2. The table where you want to link your many2many to needs atleast one field (such as name) and what you absolutely need is a field named ‘sequence’. The sequence field is an integer and will keep track of the order on your many2many. For example:
_name = 'sale.order.handle'
_description = 'Model for many2many (handle)'
_order = 'sequence'
name = fields.Char('Naam')
sequence = fields.Integer('sequence', help="Sequence for the handle.",default=10)
As you can see I created a field named sequence which is an integer. The second thing that you need for this field is to give it a default value, otherwise it will not work correctly. After you’ve created your model and fields its time to create your many2many.
2. Creating the many2many (widget)
The second step is to create a many2many which links from the table where you want to use the many2many to the table where you want to link it with. For example:
return self.pool.get('sale.order.handle').search(self.env.cr, self.env.uid, )
_inherit = 'sale.order'
print_handle_ids = fields.Many2many('sale.order.handle','sale_handle','order_id','order_handle_id','Many2many order',help='This could be used to create a print order for your report, for example.This is a drag an drop (handle) widget.',default=_get_default_print_order_ids)
As you can see I’ve inherited the model sale.order since I want to create my many2many in this model. I then created a new field and created a link to the table sale.order.handle. I’ve also created a default which links to a function. The idea behind this is to automatically fill the many2many handle with all the data from the model sale.order.handle. Ofcourse you don’t have to, this is just for the demo.
Tip: Out of safety uses you should never create a table longer than 16 characters in a many2many! The postgreSQL database cannot handle a many2many link longer than 64 characters in total. For more information see this bug report.
3. Creating the view
Now that you’ve created both your model and the many2many you only need to add the many2many to your view. The code will look like this:
<record id="view_orderinherit_orderlines" model="ir.ui.view">
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<!--Adds a new page (tab) to the view after the tab Order Lines-->
<xpath expr="//page[@string='Order Lines']" position="after">
<page name="many2manyhandledemo" string="Many2many handle demo">
<tree string="Printing order" editable="bottom">
<field name="sequence" widget="handle"/>
There isn’t to much difference with a normal many2many, there are just three things you should always do.
1. Create your own tree to render the many2many correctly.
2. always add the field ‘sequence’ in this tree.
3. call the widget with widget=”handle”. This will make the many2many drag and droppable.
And thats it, you’ve created your own many2many handle which makes items drag and droppable. The result will look something like this:
Do you want to see the source code or try this module for yourself? You can download / view it on Github.
Has this tutorial helped you, do you have any feedback or questions? Post away!