Mariano DAngelo
Mariano DAngelo

Reputation: 940

How can I search by a computed field in Odoo?

I'm trying to search by a computed field in Odoo 9. But it return all record as result.

class Version(models.Model):
    _name='product_cars_application.version'

    name = fields.Char(compute="_get_name", store=True)

    @api.one
    def _get_name(self):
        self.name = "%s %s %s (%s)" % (self.brand_id,
                                       self.model_id.name,
                                       self.vname,
                                       self.year_id)

I have tried with store=True and without it, but the name field is not stored in the databse. I have also tried to delete the column "name" from the database, then I have updated the module but it isn't storing the computation. The computed field works fine on the form view, but the name is not stored, and the search is not working.

So, how can I search by the field name?

Upvotes: 2

Views: 7915

Answers (2)

ChesuCR
ChesuCR

Reputation: 9670

I do not recommend that you use store=True in computed fields if they are not completely necessary (this is needed if you want to group by this field) because they do not work well in some cases, in spite of latest versions work better. So, I think you could do something like this:

class Version(models.Model):
    _name = 'product_cars_application.version'

    name = fields.Char(
        compute="_compute_name",
        search="_search_name",
    )

    @api.one
    def _compute_name(self):
        self.name = "%s %s %s (%s)" % (self.brand_id,
                                    self.model_id.name,
                                    self.vname,
                                    self.year_id)

    def _search_name(self, operator, value):
        """ Actually this converts a domain into another one.
            With this new domain Odoo can search well
            A list of ids is the most easy way without computed fields
                * [('id', 'in', id_list)]
        """
        if operator == 'ilike':
            name = self.env.context.get('name', False)
            if name is not False:
                id_list = []
                product_cars = self.env['product_cars_application.version'].search([])
                for car in product_cars:
                    if name in car.name:
                        id_list.append(lot.id)
                return [('id', 'in', lot_id_list)]
            else:
                return [('id', 'in', [])]
        else:
            _logger.error(
                'The field name is not searchable'
                ' with the operator: {}',format(operator)
            )

Take into account that this way to search is more inefficient than store the values in the database because you always have to loop over all the records to compute the values.

By the way, for your specific case of use, the best thing you could do is to create the field name as a normal char, that's not computed. You can set a default value to create the name. Like this the value would be stored and the problems would disappear.

Upvotes: 1

Andre Buschermöhle
Andre Buschermöhle

Reputation: 1091

Add this to your code.

 def _name_search(self,name, args=None, operator='ilike', limit=100):
    if operator == 'like': 
       operator = 'ilike'

    versions=self.search([('name', operator, name)], limit=limit)
    return versions.name_get()

 name = fields.Char(compute=_get_name, store=True,search=_name_search)

You can see details in the docs.

https://www.odoo.com/documentation/8.0/reference/orm.html

Section "Computed Fields" is for you.

Hopefully it will work. Let me know.

Upvotes: 1

Related Questions