Odoo 13 Changelog

This is an incomplete list of mostly technical changes that should be coming in Odoo 13 and which I have stumbled upon.

Some of these are yet not merged, so still have a chance of not making it in time...

This post only covers Odoo Community Edition.


  • Accounting refactoring [source], a.k.a. accounting-pocalypse. RIP account.invoice. Good luck migrating ;)
  • API key based authentication [PR]. (Note: As of 2019-08-29 this is still not merged).


Removed decorators

@api.multi [source], @api.returns [source] @api.guess, @api.noguess, @api.model_cr and other compatibility decorators [source] are removed.

@api.preupdate and @api.postupdate

As of 2019-08-29 this is still not merged.


These allow to define functions which are called before (preupdate) or after (postupdate) create() and write() for some (or all if no fields are specified) of the record's fields. This allows to have a cleaner create()/write() and avoid some code duplication.

Examples from documentation:

@api.preupdate('foo', 'bar')
def _preupdate_name(self, vals):
    vals['baz'] = vals.get('foo', "") + vals.get('bar', "")

def _postupdate_parent_id(self, vals):
    for record in self:
        if record.parent_id.customer:
            record.customer = True


A new decorator @api.depends_context(), which allows to specify context key dependencies for computed fields.

Example from documentation:

price = fields.Float(compute='_compute_product_price')

def _compute_product_price(self):
    for product in self:
        if product.env.context.get('pricelist'):
            pricelist = self.env['product.pricelist'].browse(product.env.context['pricelist'])
            pricelist = self.env['product.pricelist'].get_default_pricelist()
        product.price = pricelist.get_products_price(product).get(product.id, 0.0)

See also depends_context field attribute.

@api.onchange warning notifications

Warning returned from an onchange method can now have an extra type key. If type is notification, then the warning message will be displayed as a notification (top-right corner), instead of a dialog window, e.g.:

return {
    'domain': {'other_id': [('partner_id', '=', partner_id)]},
    'warning': {'title': "Warning", 'message': "What is this?", 'type': 'notification'},





sudo() no longer takes the ID of the user to change to (this is deprecated. Instead, it takes a boolean flag to enable/disable superuser mode. Superuser mode allows to bypass access rights without changing the ID of the current user (yay!).


with_user(user) returns the recordset in a new environment with the current user replaced with user, so it essentially is the old sudo().


record.get_base_url() should return the URL for a given record (when implemented). By default, it returns web.base.url.


There seems to be no documentation yet, but IIUC filtered_domain() allows to filter a recordset using a regular domain, e.g.:

domain = [
    ('some_field', '=', 'some_value'),

# Records having `some_field = 'some_value'`.
filtered_recordset = recordset.filter_domain(domain)

# Which is essentially equal to this:
filtered_recordset = recordset.search(
    domain + [
        ('id', 'in', recordset.ids),
# but without a call to the database. Neat!


Field (common to all)

oldname field attribute

Support for oldname field attribute is dropped and the attribute is deprecated.


This is only applicable if `mail` module is installed.

track_visibility field attribute is replaced with tracking=True|False. If tracking is an integer, then its value is also used as the sequence (replacement of track_sequence).



Specifying float field precision with digits=dp.get_precision(<application>) is deprecated, the application can now be specified directly, e.g.:

product_qty = fields.Float(
    digits='Product Unit of Measure',


Selection field values are now stored in the database (ir.model.fields.selection). There is no change in how the selection values are defined on the field, however int type selections are no longer supported.



New field type Image. Takes two additional attributes:

  • max_width
  • max_height

If at least one of max_width / max_height is provided, then the image is resized on create()/write().


New field type Many2oneReference is added for cases where the model/ID (res_model, res_id) pair is stored. Takes one additional attribute:

  • model_field - name of the field on the current model which stores the model name (res_model).


As of 2019-08-29 this is still not merged.

@at_install and @post_install test decorators, which where deprecated in v12, are removed, @tagged should be used instead, e.g.:

# Equivalent to `@at_install(True)`

# Equivalent to `@at_install(False)`

# Equivalent to `@post_install(True)`

# Equivalent to `@post_install(False)`


For an insight into more functional upcoming changes: