Odoo Development Notes

website·Indexed 30 days ago

https://lucasliu09.github.io

Technical documentation and source code analysis for Odoo, with a focus on version 16. Covers the OWL framework, including components like ListView, FormController, and ListRenderer, as well as the registry system, concurrency primitives like KeepLast, and third-party integrations such as Leaflet and SortableJS. Includes guides on installation, configuration, and Python design patterns.

Tokens
137.6K
Snippets
451
Records
737
Agent score
72%

What's inside Odoo Dev Notes

  1. Overview of the web_breadcrumb_back module

    The web_breadcrumb_back module for Odoo 16 provides a global UI enhancement that adds a dedicated 'Back to previous level' button to the left of the Control Panel breadcrumbs. It is designed to be installed globally without requiring modifications to business view XMLs. The module preserves native navigation logic and ensures consistency with 'unsaved changes' checks by reusing official Odoo navigation APIs.
  2. Overview of X2ManyField component in Odoo 16

    The X2ManyField is a core Owl component in Odoo 16 used to handle relational fields (one2many and many2many). It acts as a bridge between data management and the renderer. It is registered in the fields registry under the names one2many and many2many. Its primary responsibilities include managing CRUD operations for associated records, handling pagination, controlling view mode switching (list vs. kanban), and providing data and operation interfaces to the child renderer.
    File path: addons/web/static/src/views/fields/x2many/x2many_field.js
  3. Overview of Odoo 16 Base Automation Mechanism

    The base_automation module (located in addons/base_automation) acts as a trigger layer that hooks into Odoo's ORM methods (create, write, unlink, _compute_field_value, and onchange). It does not implement its own action engine; instead, it delegates the execution to ir.actions.server.run().

    Execution Flow: Business CRUD/Compute/Onchange/Cron $\rightarrow$ Monkey-patch/Hook $\rightarrow$ Pre-filter $\rightarrow$ Write $\rightarrow$ Post-filter $\rightarrow$ _process $\rightarrow$ ir.actions.server.sudo().run().

  4. Overview of the Odoo 16 CommandPalette

    The CommandPalette is the search console triggered by the keyboard shortcut Ctrl + K. It allows users to search for apps and menu items. In Odoo 16, the palette's functionality is driven by several registries that define categories, setup configurations, and data providers.
    // Base Component
    CommandPalette
  5. Overview of Odoo 16 Runtime Model Modification APIs

    Odoo 16 provides four APIs in BaseModel (odoo/models.py) to perform runtime modifications to model classes within the registry after it has been assembled. Unlike _inherit, which defines behavior in source code during module loading, these hooks and patches modify the class objects in the current worker process based on database configuration, environment, or testing needs.
  6. Overview of the Odoo 16 Relational Model Adapter

    In Odoo 16, basic_relational_model.js serves as an adaptation layer between the new OWL view system (@web/*) and the legacy web.BasicModel data layer. While the UI uses OWL components and the new Model base class, the underlying data management—including ORM RPC interactions, onchange events, x2many commands, and concurrency control (mutex)—is still handled by the legacy web.BasicModel.
  7. Overview of the Odoo 16 OWL Frontend Registry

    In Odoo 16 (OWL 2), the frontend uses a global registry system to manage extension points. This replaces the OWL 1 Component.register() method. The registry is a singleton exported from addons/web/static/src/core/registry.js. Modules register their components, services, or views at the top level of the JS file during module loading. These files must be included in the appropriate assets bundle to be executed. The general lifecycle is: registration occurs first, followed by the execution of startWebClient() which consumes these registrations.
  8. Overview of the ActionMenus component in Odoo 16

    ActionMenus is an OWL component in Odoo 16 responsible for displaying and executing action menus (specifically "Print" and "Action" dropdowns) located on the left side of the control panel. Its primary functions include displaying print and custom action menus, executing actions via callbacks, Action IDs, or URLs, supporting registry extensions, and handling active record contexts.
    addons/web/static/src/search/action_menus/action_menus.js
  9. Overview of Odoo stress testing with Locust

    Locust is an open-source, Python-based load testing tool used to test the performance of Web applications and APIs. It is particularly suited for Odoo stress testing because Odoo utilizes XML-RPC/JSON-RPC APIs which Locust can easily invoke. It allows developers to simulate real user operation flows rather than simple HTTP requests, providing metrics on response time, throughput, and error rates. Common use cases include performance benchmarking, capacity planning, regression testing, and bottleneck identification.
  10. Overview of Odoo 16 Form View Rendering Architecture

    The Form View rendering process in Odoo 16 is split between a renderer and a compiler to transform XML architecture into an OWL component tree.

    • FormRenderer: The rendering layer. It does not manually create DOM elements but uses useViewCompiler() to compile archInfo.xmlDoc into an OWL template, which is then rendered via t-call. It handles runtime UX logic such as window resizing, autofocus, and 'bounce' animations in read-only mode.
    • FormCompiler: A subclass of ViewCompiler that transforms the form architecture into a tree of OWL components (e.g., Field, Notebook, ViewButton). It injects necessary callbacks from the Controller into the downstream components' props.
    • useViewCompiler(): A hook that provides a compilation cache based on the ViewCompiler.name and rawArch to prevent redundant compilations.
  11. Inject dynamic content into views using QWeb templates and get_view

    To dynamically insert content into a view, you can render a QWeb template to a string, convert it to an etree node, and append it to the view's architecture.

    Key technical requirements:

    1. Use ir.qweb._render to generate the XML string from a template.
    2. Use ir.ui.view.postprocess_and_fields to process the new node and retrieve the required model fields.
    3. Merge the new fields into the res["models"] dictionary to ensure the UI can load the necessary data.
    # Helper to merge model fields
    def _merge_view_fields(all_models: dict, new_models: dict):
        for model, view_fields in new_models.items():
            if model in all_models:
                all_models[model] = tuple(set(all_models[model]) | set(view_fields))
            else:
                all_models[model] = tuple(view_fields)
    
    class XXX():
        def _add_content(self, params=None):
            if params is None: params = {}
            str_element = self.env["ir.qweb"]._render("template_id", params)
            return etree.fromstring(str_element)
    
        @api.model
        def get_view(self, view_id=None, view_type="form", **options):
            res = super(xx, self).get_view(view_id=view_id, view_type=view_type, **options)
            View = self.env["ir.ui.view"]
            if view_type == 'form':
                doc = etree.XML(res["arch"])
                all_models = res["models"].copy()
                for node in doc.xpath("//div[@name='xxxx']"):
                    if self.env.context.get('context1'):
                        new_node = self._add_content()
                        new_arch, new_models = View.postprocess_and_fields(new_node, self._name)
                        new_node = etree.fromstring(new_arch)
                        node.append(new_node)
                        _merge_view_fields(all_models, new_models)
                res["arch"] = etree.tostring(doc)
                res["models"] = frozendict(all_models)
            return res