Odoo Help

Welcome!

This community is for beginners and experts willing to share their Odoo knowledge. It's not a forum to discuss ideas, but a knowledge base of questions and their answers.

0

[SOLVED] - Add more image fields (not named "image", "image_medium", "image_small") and use the get/set/resize functions for them

By
Roberto Cocchiararo
on 1/22/15, 10:51 AM 955 views

Hi 

I need to add more images to a model that already had 1 image field (or 3, for the full/medium/small sizes).

It originally fetched the images from the brand of the vehicle, but i modified it to have it´s own, for which i succeeded.

This this task, the following Fields are used:

        'image': fields.binary("Foto",
            help="Foto avatar del auto"),
        'image_medium': fields.function(_get_image, fnct_inv=_set_image,
            string="Foto mediana", type="binary", multi="_get_image",
            store = {
                'fleet.vehicle': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
            },
            help="Foto avatar mediana para form y kanban"),
        'image_small': fields.function(_get_image, fnct_inv=_set_image,
            string="Foto chica", type="binary", multi="_get_image",
            store = {
                'fleet.vehicle': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
            },
            help="Foto avatar chica para form y kanban"),

The functions are:

    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)

As you can see, the "image" field is a binary field, and the other 2 are functional fields. Those fields use the get/set methods that at the same time use methods (or functions? :P) from "/tools/image.py" (those are imported).

image.py has a a function for resizing images, and then wrappers for fixed sizes (big 1204x1024, medium 128x128, small 64x64), and and also a function for GETTING the correct size images.

Form views use the "_medium" sized images, since the normal ones are too big.

I added more image fields (for example, "image-engine", "image-engine_medium", "image-engine_small".

At first i tried using the same get/set functins, but that made it so that editing the new fields would actually edit "image" and its derivate sizes.

Then i created specific "set and get" functions for my new field:

 'image-motor': fields.binary("Foto",
            help="Foto motor"),
        'image-motor_medium': fields.function(_get_image_motor, fnct_inv=_set_image_motor,
            string="Foto mediana", type="binary", multi="_get_image_motor",
            store = {
                'fleet.vehicle': (lambda self, cr, uid, ids, c={}: ids, ['image-motor'], 10),
            },
            help="Foto motor mediana para form y kanban"),

    def _get_image_motor(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_motor(self, cr, uid, id, name, value, args, context=None):
        return self.write(cr, uid, [id], {'image-motor': tools.image_resize_image_big(value)}, context=context)

With that, when i create a NEW car, and add the images, they are stored, but NOT resized, so both the full size field and the _medium one get the same image.

Then, if i edit the _medium field, it remais with the original image, and the "full size" one is modified (i should only use the _medium sized field in my form view, but i added both for testing when it seemd not to work).

If i edit a pre-created car or i create a car without this image and i try to add it later, the _medium field remains empty, and the normal one gets the image.

If i edit the "normal sized" field, it is modified, and the _medium one remains unchanged.

I am not sure if this happens because i should use something different from "obj.image" in the "get" function, or somethign different from "value" in the set one.

Or maybe it does not work because the "image_resize_image_big" (image.py) is hardcoded to accept only "image", "image_medium", "image_small" as parameters?

I am clearly not well versed in python, i have "general programing knowledge" and i started only adding new fields, and my needs grow the more i see i can try :P

I will now try defining my own resize wrappers, and if that fails my own resize function, always copying the original ones and modifying them for my new field names, but i find it weird that i need to create specific ones for each field if it is not named like the "lone image fields" odoo sometimes has in it´s models.

0
Roberto Cocchiararo
On 1/22/15, 3:05 PM

Ahhh success, how much i like you XD

I copied the "get" function from "image.py", modified it, and modified my get/set for the functional fields:

def image_get_resized_images_sav(base64_source, return_big=False, return_medium=True, return_small=False,
    big_name='image', medium_name='image_medium', small_name='image_small',
    avoid_resize_big=True, avoid_resize_medium=False, avoid_resize_small=False):
    """ Standard tool function that returns a dictionary containing the    big, medium and small versions of the source image. This function
        is meant to be used for the methods of functional fields for models using images.
        
        :param return_{..}: if set, computes and return the related resizing of the image
        :param {..}_name: key of the resized image in the return dictionary;
            'image', 'image_medium' and 'image_small' by default.
        :param avoid_resize_[..]: see avoid_if_small parameter
        :return return_dict: dictionary with resized images, depending on previous parameters.
    """
    return_dict = dict()
    #if return_big:
    #    return_dict[big_name] = tools.image_resize_image_big(base64_source, avoid_if_small=avoid_resize_big)
    if return_medium:
        return_dict[medium_name] = tools.image_resize_image(base64_source, size=(384, 384), encoding='base64', filetype=None, avoid_if_small=True)
    #if return_small:
    #    return_dict[small_name] = tools.image_resize_image_small(base64_source, avoid_if_small=avoid_resize_small)
    return return_dict

That function just returns the "medium" image, but it actually returns an image of a bigger size XD

Then my set functions were already fine, and my get functions had to be modified like:

    #General
    def _get_image_general(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] = image_get_resized_images_sav(obj['image-general'], return_big=False, return_medium=True, return_small=False, big_name='image-general', medium_name='image-general_medium')
        return result

    def _set_image_general(self, cr, uid, id, name, value, args, context=None):
        return self.write(cr, uid, [id], {'image-general': tools.image_resize_image_big(value)}, context=context)

I found no way for NOT defining a get/set for each field, but it works.

Your Answer

Please try to give a substantial answer. If you wanted to comment on the question or answer, just use the commenting tool. Please remember that you can always revise your answers - no need to answer the same question twice. Also, please don't forget to vote - it really helps to select the best questions and answers!

About This Community

This community is for professionals and enthusiasts of our products and services. Read Guidelines

Question tools

2 follower(s)

Stats

Asked: 1/22/15, 10:51 AM
Seen: 955 times
Last updated: 3/16/15, 8:10 AM