Odoo 模块升级注意事项
Jeff wang

7.0 8.0

       引入 新 ORM API


8.0 9.0

       select = True         ->           index = True

       Xml继承时不允许用 string 来定位元素

       noupdate=0”的时候建议不写 <data> 节点


9.0 10.0


       find . -type f -name '*.py' | xargs sed -i 's/from openerp/from odoo/g

       __opener__.py     ->      __manifest__.py

       <openerp>         ->      <odoo>

       @api.one @api.onchange不能一起用

       base.group_configuration -> base.group_system

       Copy方法从 @api.one ->  @api.multi

       base.group_sale_salesman > sales_team.group_sale_salesman.

       base.group_sale_salesman_all_leads > sales_team.group_sale_salesman_all_leads.

       base.group_sale_manager > sales_team.group_sale_manager.


10.0 11.0

       find . -name "*.py" -exec sed -i "/#.*coding\: /d" {} \;)

       2to3 -wnj4 --no-diffs .


       配置放在 res.config.settings

       For v10 ir.values entries:

       if they are for showing an option under "Print" or "Actions" dropdown menu, remove the record and just add a field binding_model_id on the ir.actions.act_window linked record. Add binding_type = report if the ir.values had key2 = client_print_multi.

       if they are for having default values, use instead the model ir.default.

       If you use reports, report module has been split between base and web:

       Change all references of ir.actions.report.xml by ir.actions.report, as the model has been changed.

       Replace t-call occurrences of base report templates:

       report.external_layout > web.external_layout.

       report.external_layout_header: No direct equivalent. You need to insert the changes inside div class="header o_clean_header"> element of the web.external_layout_? view, being ? one of the available "themes" (background, boxed, clean and standard in core)

       report.external_layout_footer: the same as above, but looking inside <div class="footer o_background_footer"> element.

       report.html_container > web.html_container.

       report.layout > web.report_layout.

       report.minimal_layout > web.minimal_layout.

       Remove group_ids field in ir.config_parameter records, and read/write them with sudo() instead

       If using widget kanban_state_selection in any view, change it to just state_selection.

       If you create ir.cron in module setup you have to change:

       model (string) -> model_id (m2o to model)

       function (string) + args (string) -> code (eg: model.cron_that_does_something())

       colors attribute in <tree> tag has been replaced by decoration-* (warning, info, danger...) attributes (bootstrap codes) with the condition as value for each.

11.0 12.0

       If you handle dates and datetimes, you might need to adapt your code now that Odoo returns always native Python objects, so no more fields.Date/Datetime.from_string is needed. For converting old style date/datetime strings to Python object, use fields.Date.to_date and fields.Datetime.to_datetime methods.

       If you overwrite create method (in a new model or in an inherited one), look if you can apply decorator @api.model_create_multi for batch mode creation. See https://www.youtube.com/watch?v=KhDg-t0F_T8 for more details.

       If your model uses _parent_store = True, then you should remove parent_left and parent_right fields, and add a new one parent_path = fields.Char(index=True). For providing full support when migrating, a post-migration script should be done calling env['model_name']._parent_store_compute() for filling this new field.

       All <label> elements in views must have a for="" attribute.

       All <filter> elements in search views must have a name attribute.

       All <button> elements in a tree view should have a string attribute for accessibility.

       Convert your SASS styles to SCSS.

       Related fields are now read only by default. If your code relies on the default contrary, you should add readonly=False in your field definition.

       base module has reorganized all the model files to include everything inside models folder. If you import that files, you should change import path. You can automate most of these changes with these bash commands:find . -type f -name '*.py' | xargs sed -i 's/from odoo.addons.base.res/from odoo.addons.base.models/g' find . -type f -name '*.py' | xargs sed -i 's/from http://odoo.addons.base.ir/from odoo.addons.base.models/g'

       If you need to generate a PDF in tests, you have to pass the context key force_report_rendering=True for getting that instead of an HTML, as now the method qweb_render_pdf defaults to qweb_render_html on test environment.

       On website modules, website_published field, that comes from website.published.mixin, turns to computed non stored, and the stored value is now is_published. You will need migration scripts for renaming the field.

12.0 13.0

       Remove all the decorators @api.multi, @api.returns, @api.one, @api.cr, @api.model_cr from the code. Now they are all multi-record by default. Except the first one (@api.multi), you will need to adapt the code to the behavior change.

       Check that all "compute" methods of non-stored computed fields assign a value in any case to the field, even if it is a falsy one. Or if they are stored, at least they have an initialization value (a default for example). You can use the expression self.<field> = ... at the beginning of the compute for pre-assigning a value to all records.

       Computed stored fields will keep their previous value if not assigned during the compute method, so don't rely on any expected default value.

       Multi-company record rules now need to have this general form: ['|',('company_id','=',False),('company_id','in',company_ids)], and you need to add migration script as well when being noupdate="1" record (which should be the majority). See https://github.com/OCA/credit-control/pull/54/commits/162cde23fe5c0dd12f7de1fa01d36a0bc156008e for an example.

       For the rest of multi-company considerations, see https://www.odoo.com/documentation/13.0/howtos/company.html.

       Replace sudo(user) (but keep sudo()). Use with_user(user) instead.

       Change track_visibility="..." field attribute by tracking=True.

       Remove all the oldname field attributes in the code. If they were added in previous version, they have served their function any way, and now in this version it's not supported, so if you have the need, create a migration script and use openupgradelib's rename_fields method.

       Remove view_type tag on action window XML definition. It's now always form (tree is not supported since 11.0 any way).

       Remove multi field from ir.actions.act_window models. Now you have binding_view_types field for indicating in which view the action will be available: list, form or empty for both. If declaring the action through the accelerator tag <act_window>, then use the attribute binding_views. src_model is also replaced by binding_model in <act_window> tag or binding_model_id in <record> tag. More reference in https://github.com/odoo/odoo/pull/24738/commits/33d51480688065e367eb646f12b89d721749cac9.

       If having an smart-button for active field, with widget toggle_button / boolean_button, the archive/unarchive actions are available without doing anything more, so you can remove it. And the new paradigm is to put instead a ribbon when archived with the code:

       <widget name="web_ribbon" text="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/> <field name="active" invisible="1" />

       If using any decimal precision in float fields (example: import odoo.addons.decimal_precision as dp; x = fields.Float(digits=dp.get_precision("Account"))), now the qualifier is put directly without the need of importing anything and simplifying syntax: x = fields.Float(digits="Account").

       In the manifest, rename python dependencies to use the PyPI distribution name instead of the import name (see https://github.com/odoo/odoo/pull/25549 for more information)

       If you have .env.user.company_id, you need to change it to .env.company if the intended use is to get "current active company".

       If inheriting hr.employee use hr.employee.base instead. See https://github.com/OCA/hr/pull/1001 and https://github.com/odoo/odoo/commit/c9ca3761464413327d2beb697553a3ccd7eef4d1

       On mail templates, you can't use format_tz anymore. Instead, use format_datetime with explicit tz and date format arguments. Example: format_tz(object.date) becomes format_datetime(object.date, tz=object.tz, dt_format="dd/MM/yyyy HH:mm")

       In JavaScript, replace jQuery promises ($) by native Promise (example: $.when() becomes Promise.resolve()).

       In JavaScript, replace config.debug sentence for getting if in debug mode by config.isDebug().

       If the module is touching Accounting part, see https://github.com/OCA/maintainer-tools/issues/430 for the structural changes detected in it.

13.0 14.0

       If you add new values in a selection field through selection_add, you have to define a new ondelete= attribute setting the value to assign for each previous value in case of uninstallation. More info at https://github.com/odoo/odoo/commit/f0481392c6501cae2c38359f526da1eefa451337. Example: selection_field = fields.Selection(selection_add=[("foo", "Foo")], ondelete={"foo": "set null"}).

       In the XML views, the invisible and readonly attributes no longer support dynamic expressions like state=='draft'. When using those, use the attrs attribute instead. You can only use them for direct context queries like context.get('invisible').

       XML shortcut tags <act_window> and <report> are no longer valid, and must be replaced by its full definition through <record> tag.

       If there are transient models, you have to add explicit security ACLs for them (and optionally record rules).

       If you were overriding _compute_display_name for getting a different display_name, you should now override name_get method and add there the needed @api.depends. This is not valid though if you want to make display_name stored for allowing a direct name_search. Other option is to override name_search instead.

       Remove size=X attribute in Char fields, as it's no longer valid for restricting the size of the strings.

       _name_search is now returning ids instead of the name_get style tuple (list of (id, display_name)): https://github.com/odoo/odoo/commit/1f48130d2bd055835ee428a21922331d126285a3

       Remove global field assignation line in record rules, as it's a computed field.

       Replace appearances of .with_context(force_company=...) with .with_company(...).

       The access to ir.actions.* objects has been removed, so you need to use sudo or interact via the /web/action/load controller. See odoo/odoo#53335 for more information.

       If you are posting messages in the chatter with a subtype, now the description of the subtype is shown on the UI, so you don't need to repeat such text on the body, and also take this into account for putting good subtypes descriptions (from the functional perspective).

14.0 15.0

       t-raw QWeb directives are replaced by t-out/t-esc ones, with the optional Python tool markupsafe.Markup for escaping HTML content in server side. HTML fields apply directly the markup when used on QWeb. See https://github.com/odoo/odoo/commit/01875541b1a8131cbhttps://github.com/odoo/odoo/pull/70004 and https://github.com/odoo/odoo/pull/70004 for more details.

       The access to ir.model* objects has been removed, so you need to use sudo, or use the existing methods for getting usual data. See https://github.com/odoo/odoo/pull/69120 for more info.

       Jinja syntax in mail templates has been replaced by 2 languages:

       Qweb for the body of the mail template.

       inline_template, which is similar to Jinja, but with expressions enclosed by {{ and }} instead of ${ and }. It's used in fields like subject, email_from, email_to, etc.

       More info and examples of replacing at https://github.com/odoo/odoo/pull/77074

       If you migrate some .js file to an ES module (they start with /** @odoo-module **/), rename the file to finish with .esm.js (rename also the assets) to enable ESLint compatibility.

       Assets are now directly declared in the manifest. You should move .js and .scss links from templates to __manifest__.py file. They should be placed under "assets" key with the following structure:

       "assets": { "web.assets_backend": ["path to .js or css, like /module_name/static/src/...",...], "web.assets_qweb": ["path to .xml, like /module_name/static/src/...",...], "...": [...], },

       Notice that there is no more "qweb" key in __manifest__.py. Instead of it, you must link all qweb .xml in web.assets_qweb bundle, as shown above.

       The path to the files is now relative to the root folder, not the module folder.

       Illustrative example: https://github.com/OCA/credit-control/pull/154/commits/c2349c52dc5385f46c94bfa8fc0db2381b251fc8

       You can use globs as well for not having to declare each individual file.

       Replace SavepointCase by TransactionCase in tests, as they are now the same. The old one still exists as an alias, but a warning will arise, and next version will remove such alias. More info at https://github.com/odoo/odoo/pull/62031

       If you write a hook or any code that requires to create a new environment, there's no need of using the with Environment.manage(): context statement anymore.

       Put unaccent=False on field definitions where no distinction should be made between accented words, for getting better performance on searches. Example: parent_path field. See https://github.com/odoo/odoo/pull/76436 for more details.

15.0 - 16.0

       If you are overriding name_search method in your module, you may make use now of new _rec_names_search class variable to expose the fields to search for without requiring the method override. More details at https://github.com/odoo/odoo/commit/3155c3e425581b71491844e7f9a3dd76a9f245a4.

       Any view with groups_id on it now has to move such groups to the elements of the view. But now you can put groups attribute in a view field instead of isolating it on a view without fear of an access error. Check both things in https://github.com/odoo/odoo/pull/98551 and https://github.com/odoo/odoo/pull/95729.

       If using fields_get_keys() method for getting fields definition, now use directly _fields variable or get_views() method.

       If using get_xml_id() method for getting an ID, now use the method get_external_id().

       The methods flush() and recompute() are deprecated. Use flush_model(), flush_recordset() or env.flush_all() instead depending on the needed granularity.

       The methods refresh() and invalidate_cache() are deprecated. Use invalidate_model(), invalidate_recordset() or env.invalidate_all() instead depending on the needed granularity.