post_load

What do we know from comments in odoo source?

# Call the module's post-load hook. This can done before any model or
# data has been initialized. This is ok as the post-load hook is for
# server-wide (instead of registry-specific) functionalities.

What is it actually for?

For Monkey patches

../../_images/monkey-patch.jpg

Example of monkey patch in odoo

from odoo import tools

def new_image_resize_images(...)
    ...

tools.image_resize_images = new_image_resize_images

Why shall we use post_load to apply monkey patch?

Note

Since odoo 12 monkey patch could be applied without post_load, but it’s still recommended to use it to be sure.

Because otherwise monkey patch will be applied every time it is available in addons path. It happens because odoo loads python files of a module if there is a static folder in the module (no matter if the module is installed or not – see load_addons method in http.py file of odoo source).

How to use post_load?

You need to define a function available in __init__.py file of the module. Then set that function name as value of "post_load" attribute in module manifest.

Example?

Sure. E.g. from telegram module.

In __openerp__.py

    ...
    "post_load": "telegram_worker",
    "pre_init_hook": None,
    "post_init_hook": None,
    "installable": True,
    "auto_install": False,
    "application": True,
}

In __init__.py

from odoo.service.server import PreforkServer

...

def telegram_worker():
    # monkey patch
    old_process_spawn = PreforkServer.process_spawn

    def process_spawn(self):
        old_process_spawn(self)
        while len(self.workers_telegram) < self.telegram_population:
            # only 1 telegram process we create.
            self.worker_spawn(WorkerTelegram, self.workers_telegram)

    PreforkServer.process_spawn = process_spawn
    old_init = PreforkServer.__init__

    def __init__(self, app):
        old_init(self, app)
        self.workers_telegram = {}
        self.telegram_population = 1
    PreforkServer.__init__ = __init__

Something else we need to know?

Yes.

Additionally, if you need to apply monkey patch before any other initialisation, the module has to be added to server_wide_modules parameter.

Other usage of post_load?

In case of extending pos-box modules (e.g. hw_escpos), you probably need to use post_load, because importing hw_escpos from your module runs posbox specific initialisation.

Example from hw_printer_network module:

In __manifest__.py

    ...
    "post_load": "post_load",
    "pre_init_hook": None,
    "post_init_hook": None,
    "installable": True,
    "auto_install": False,
    "application": True,
}

In __init__.py

def post_load():
    from . import controllers

In controllers/hw_printer_network_controller.py

# first reason of using post_load
from odoo.addons.hw_escpos.escpos import escpos
import odoo.addons.hw_escpos.controllers.main as hw_escpos_main

...

# second reason - monkey patch:
driver = UpdatedEscposDriver()
hw_escpos_main.driver = driver