overriding write() method in odoo 8 results in RuntimeError: maximum recursion depth exceeded

dnl.re picture dnl.re · Sep 21, 2015 · Viewed 9.2k times · Source

This seems to be a significant simple problem, but somehow I cant find a solution.

As I press the save button the write method will be executed. I want to change a value (or call a function) of the current model every time the write method is called, so I have overridden the write() method of my model as

@api.multi
def write(self, vals):
    self.flaeche = 37
    return super(lager, self).write(vals)

(the model is lager.py and the field is flaeche = fields.Float(string=u"Fläche (m²)"))

The Error: RuntimeError: maximum recursion depth exceeded

Traceback (most recent call last):
  File "/home/tertia/workspace/odoo8/openerp/http.py", line 530, in _handle_exception
    return super(JsonRequest, self)._handle_exception(exception)
  File "/home/tertia/workspace/odoo8/openerp/http.py", line 567, in dispatch
    result = self._call_function(**self.params)
  File "/home/tertia/workspace/odoo8/openerp/http.py", line 303, in _call_function
    return checked_call(self.db, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/service/model.py", line 113, in wrapper
    return f(dbname, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/http.py", line 300, in checked_call
    return self.endpoint(*a, **kw)
  File "/home/tertia/workspace/odoo8/openerp/http.py", line 796, in __call__
    return self.method(*args, **kw)
  File "/home/tertia/workspace/odoo8/openerp/http.py", line 396, in response_wrap
    response = f(*args, **kw)
  File "/home/tertia/workspace/odoo8/openerp/addons/web/controllers/main.py", line 936, in call_kw
    return self._call_kw(model, method, args, kwargs)
  File "/home/tertia/workspace/odoo8/openerp/addons/web/controllers/main.py", line 928, in _call_kw
    return getattr(request.registry.get(model), method)(request.cr, request.uid, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 241, in wrapper
    return old_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 363, in old_api
    result = method(recs, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/custom_modules/g4e_config/lager.py", line 225, in write
    self.flaeche = 37
  File "/home/tertia/workspace/odoo8/openerp/fields.py", line 853, in __set__
    record.write({self.name: self.convert_to_write(value)})
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 239, in wrapper
    return new_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/custom_modules/g4e_config/lager.py", line 225, in write
    self.flaeche = 37
  File "/home/tertia/workspace/odoo8/openerp/fields.py", line 853, in __set__
    record.write({self.name: self.convert_to_write(value)})
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 239, in wrapper
    return new_api(self, *args, **kwargs)

.....

  File "/home/tertia/workspace/odoo8/custom_modules/g4e_config/lager.py", line 225, in write
    self.flaeche = 37
  File "/home/tertia/workspace/odoo8/openerp/fields.py", line 853, in __set__
    record.write({self.name: self.convert_to_write(value)})
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 239, in wrapper
    return new_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/custom_modules/g4e_config/lager.py", line 225, in write
    self.flaeche = 37
  File "/home/tertia/workspace/odoo8/openerp/fields.py", line 853, in __set__
    record.write({self.name: self.convert_to_write(value)})
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 239, in wrapper
    return new_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/custom_modules/g4e_config/lager.py", line 224, in write
    super(lager, self).write(vals)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 239, in wrapper
    return new_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 546, in new_api
    result = method(self._model, cr, uid, self.ids, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/addons/mail/mail_thread.py", line 435, in write
    self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context, values=values)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 241, in wrapper
    return old_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/addons/mail/mail_thread.py", line 1883, in message_auto_subscribe
    header_subtype_ids = subtype_obj.search(cr, uid, ['|', ('res_model', '=', False), ('parent_id.res_model', '=', self._name)], context=context)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 241, in wrapper
    return old_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/models.py", line 1639, in search
    return self._search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 241, in wrapper
    return old_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/models.py", line 4621, in _search
    query = self._where_calc(cr, user, args, context=context)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 241, in wrapper
    return old_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/models.py", line 4444, in _where_calc
    e = expression.expression(cr, user, domain, self, context)
  File "/home/tertia/workspace/odoo8/openerp/osv/expression.py", line 646, in __init__
    self.parse(cr, uid, context=context)
  File "/home/tertia/workspace/odoo8/openerp/osv/expression.py", line 847, in parse
    right_ids = comodel.search(cr, uid, [(path[1], operator, right)], context=context)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 241, in wrapper
    return old_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/models.py", line 1639, in search
    return self._search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 241, in wrapper
    return old_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/models.py", line 4615, in _search
    self.check_access_rights(cr, access_rights_uid or user, 'read')
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 241, in wrapper
    return old_api(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/models.py", line 3477, in check_access_rights
    return self.pool.get('ir.model.access').check(cr, uid, self._name, operation, raise_exception)
  File "/home/tertia/workspace/odoo8/openerp/api.py", line 241, in wrapper
    return old_api(self, *args, **kwargs)
  File "<string>", line 2, in check
  File "/home/tertia/workspace/odoo8/openerp/tools/cache.py", line 117, in lookup
    r = d[key]
  File "/home/tertia/workspace/odoo8/openerp/tools/func.py", line 66, in wrapper
    return func(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/tools/lru.py", line 38, in __getitem__
    self[a[0]] = a[1]
  File "/home/tertia/workspace/odoo8/openerp/tools/func.py", line 66, in wrapper
    return func(self, *args, **kwargs)
  File "/home/tertia/workspace/odoo8/openerp/tools/lru.py", line 44, in __setitem__
    del self[obj]

The same happens when I want to call a function of the lager model. What am I doing wrong?

Answer

Ludwik Trammer picture Ludwik Trammer · Sep 22, 2015

The problem is that by writing self.flaeche = 37 you are changing the record, which means implicitly calling the write() method on the model. When you call write() from write() you obviously end up with recursion.

You can do something similar to this instead:

@api.multi
def write(self, vals):
    vals['flaeche'] = 37
    return super(lager, self).write(vals)

This way there are no additional writes - you just change the values for a write that was about to happen anyway.

If you want to allow people to explicitly overwrite the value of 37 you can do this:

@api.multi
def write(self, vals):
    if 'flaeche' not in vals:
        vals['flaeche'] = 37
    return super(lager, self).write(vals)