Hi guys,
In this tutorial I will learn you how to create a new field that saves images, how to upload them correctly in your database and how to automatically resize them. With this demo you’ll learn how to instantly (automatically) resize uploaded images.
Tip:view my sample module here.
1. Create new fields
The first step is to create a new model and the new fields. For this demo I will create a clean, new table, but you could just simply add fields to an existing model.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class upload_images(osv.osv): _name = 'upload_images.tutorial' _description = 'Tutorial image uploading' _columns = { 'name': fields.char('Name', required=True, translate=True), 'image': fields.binary("Image", help="This field holds the image used as image for our customers, limited to 1024x1024px."), 'image_medium': fields.function(_get_image, fnct_inv=_set_image, string="Image (auto-resized to 128x128):", type="binary", multi="_get_image", store={ 'upload_images.tutorial': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10), },help="Medium-sized image of the category. It is automatically "\ "resized as a 128x128px image, with aspect ratio preserved. "\ "Use this field in form views or some kanban views."), 'image_small': fields.function(_get_image, fnct_inv=_set_image, string="Image (auto-resized to 64x64):", type="binary", multi="_get_image", store={ 'upload_images.tutorial': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10), }, help="Small-sized image of the category. It is automatically "\ "resized as a 64x64px image, with aspect ratio preserved. "\ "Use this field anywhere a small image is required."), } |
As you can see I will create 4 fields. One to fill in a name and three fields of the type binary, which will be used to upload the images on. Every image field calls a field.function, which will then automatically resize the images:
1 2 3 4 5 6 7 8 |
def _get_image(self, cr, uid, ids, name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): result[obj.id] = tools.image_get_resized_images(obj.image) return result def _set_image(self, cr, uid, id, name, value, args, context=None): return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context) |
So, what exactly does this do? The function get_image will find the correct image and returns it. Then the second function goes off, named _set_image. This function will call a pre-built function from Odoo to automatically resize the image.
2. Showing the new fields
Now that the model and fields are done they should also be showed. In my sample I will create a new menu item named ‘Images’ in the sales module, but you could just leave this out or place it anywhere else.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<record id="action_upload_images" model="ir.actions.act_window"> <field name="name">Images</field> <field name="type">ir.actions.act_window</field> <field name="res_model">upload_images.tutorial</field> <field name="view_type">form</field> <field name="view_id" ref=""/> <field name="view_mode">tree,form</field> </record> <menuitem id="menu_our_customers" action="action_upload_images" parent="base.menu_sales" sequence="14"/> <record id="view_images_form" model="ir.ui.view"> <field name="name">upload_images.tutorial.form</field> <field name="model">upload_images.tutorial</field> <field name="arch" type="xml"> <form string="Our images"> <group> <field name="name"/> <field name="image_medium"/> <field name="image_small"/> </group> </form> </field> </record> |
This will create a new menu item with the name ‘Images’, which is triggered by the action action_upload_images when the user clicks on it. The third record, view_images_form will show the fields and gives us the ability to visualise it as we want. Result:
3. Printing the images on a report
Now that the images can be saved and resized you should also be able to print them in your report!
Printing an image in a report is really easy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<table> <tr> <td style="width:33% !important;"> Full size:<br/> <span t-field="o.image" t-field-options="{"widget": "image"}"/> </td> <td style="width:33% !important;"> 128x128:<br/> <span t-field="o.image_medium" t-field-options="{"widget": "image"}"/> </td> <td style="width:33% !important;"> 64x64:<br/> <span t-field="o.image_small" t-field-options="{"widget": "image"}"/> </td> <td style="width:33% !important;"> Name:<br/> <span t-field="o.name"/> </td> </tr> </table> |
This code will print the images out in the original format, in the 128x128px size and in 64x64px size. You simply need to call the image widget and you can print them out. When you’d print the report you would get something like this:
Tip: This whole tutorial is written in the Odoo V7 API. This is because Odoo 8 does not have fields.function and would complicate the task. If you’d really want it in Odoo 8 API you should have a look at computed fields.
Tip #2: You could also create an on_change event which then fills up different fields with different sizes of the images. This however would fill up the database much faster and is the reason why this is not in this tutorial.