odoo启动-加载模块(load_modules)
最佳答案 问答题库678位专家为你答疑解惑
odoo启动-加载模块(load_modules)
odoo每次启动的时候都会加载模块,加载模块的过程就是调用load_modules 函数
在函数位于 odoo\modules\loading.py
代码中注释也写的很清楚,共分了9个步骤,其实是8个步骤。
这个函数的作用是为一个新创建的注册表对象加载模块,这是Registry.new()的一部分,不应该用在其他地方。
def load_modules(registry, force_demo=False, status=None, update_module=False):""" Load the modules for a registry object that has just been created. Thisfunction is part of Registry.new() and should not be used anywhere else."""initialize_sys_path()force = []if force_demo:force.append('demo')models_to_check = set()with registry.cursor() as cr:# prevent endless wait for locks on schema changes (during online# installs) if a concurrent transaction has accessed the table;# connection settings are automatically reset when the connection is# borrowed from the poolcr.execute("SET SESSION lock_timeout = '15s'")if not odoo.modules.db.is_initialized(cr):if not update_module:_logger.error("Database %s not initialized, you can force it with `-i base`", cr.dbname)return_logger.info("init db")odoo.modules.db.initialize(cr)update_module = True # process auto-installed modulestools.config["init"]["all"] = 1if not tools.config['without_demo']:tools.config["demo"]['all'] = 1if 'base' in tools.config['update'] or 'all' in tools.config['update']:cr.execute("update ir_module_module set state=%s where name=%s and state=%s", ('to upgrade', 'base', 'installed'))# STEP 1: LOAD BASE (must be done before module dependencies can be computed for later steps)graph = odoo.modules.graph.Graph()graph.add_module(cr, 'base', force)if not graph:_logger.critical('module base cannot be loaded! (hint: verify addons-path)')raise ImportError('Module `base` cannot be loaded! (hint: verify addons-path)')if update_module and odoo.tools.table_exists(cr, 'ir_model_fields'):# determine the fields which are currently translated in the databasecr.execute("SELECT model || '.' || name FROM ir_model_fields WHERE translate IS TRUE")registry._database_translated_fields = {row[0] for row in cr.fetchall()}# processed_modules: for cleanup step after install# loaded_modules: to avoid double loadingreport = registry._assertion_reportloaded_modules, processed_modules = load_module_graph(cr, graph, status, perform_checks=update_module,report=report, models_to_check=models_to_check)load_lang = tools.config.pop('load_language')if load_lang or update_module:# some base models are used below, so make sure they are set upregistry.setup_models(cr)if load_lang:for lang in load_lang.split(','):tools.load_language(cr, lang)# STEP 2: Mark other modules to be loaded/updatedif update_module:env = api.Environment(cr, SUPERUSER_ID, {})Module = env['ir.module.module']_logger.info('updating modules list')Module.update_list()_check_module_names(cr, itertools.chain(tools.config['init'], tools.config['update']))module_names = [k for k, v in tools.config['init'].items() if v]if module_names:modules = Module.search([('state', '=', 'uninstalled'), ('name', 'in', module_names)])if modules:modules.button_install()module_names = [k for k, v in tools.config['update'].items() if v]if module_names:modules = Module.search([('state', 'in', ('installed', 'to upgrade')), ('name', 'in', module_names)])if modules:modules.button_upgrade()env.flush_all()cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base'))Module.invalidate_model(['state'])# STEP 3: Load marked modules (skipping base which was done in STEP 1)# IMPORTANT: this is done in two parts, first loading all installed or# partially installed modules (i.e. installed/to upgrade), to# offer a consistent system to the second part: installing# newly selected modules.# We include the modules 'to remove' in the first step, because# they are part of the "currently installed" modules. They will# be dropped in STEP 6 later, before restarting the loading# process.# IMPORTANT 2: We have to loop here until all relevant modules have been# processed, because in some rare cases the dependencies have# changed, and modules that depend on an uninstalled module# will not be processed on the first pass.# It's especially useful for migrations.previously_processed = -1while previously_processed < len(processed_modules):previously_processed = len(processed_modules)processed_modules += load_marked_modules(cr, graph,['installed', 'to upgrade', 'to remove'],force, status, report, loaded_modules, update_module, models_to_check)if update_module:processed_modules += load_marked_modules(cr, graph,['to install'], force, status, report,loaded_modules, update_module, models_to_check)if update_module:# set up the registry without the patch for translated fieldsdatabase_translated_fields = registry._database_translated_fieldsregistry._database_translated_fields = ()registry.setup_models(cr)# determine which translated fields should no longer be translated,# and make their model fix the database schemamodels_to_untranslate = set()for full_name in database_translated_fields:model_name, field_name = full_name.rsplit('.', 1)if model_name in registry:field = registry[model_name]._fields.get(field_name)if field and not field.translate:_logger.debug("Making field %s non-translated", field)models_to_untranslate.add(model_name)registry.init_models(cr, list(models_to_untranslate), {'models_to_check': True})registry.loaded = Trueregistry.setup_models(cr)# check that all installed modules have been loaded by the registryenv = api.Environment(cr, SUPERUSER_ID, {})Module = env['ir.module.module']modules = Module.search(Module._get_modules_to_load_domain(), order='name')missing = [name for name in modules.mapped('name') if name not in graph]if missing:_logger.error("Some modules are not loaded, some dependencies or manifest may be missing: %s", missing)# STEP 3.5: execute migration end-scriptsmigrations = odoo.modules.migration.MigrationManager(cr, graph)for package in graph:migrations.migrate_module(package, 'end')# check that new module dependencies have been properly installed after a migration/upgradecr.execute("SELECT name from ir_module_module WHERE state IN ('to install', 'to upgrade')")module_list = [name for (name,) in cr.fetchall()]if module_list:_logger.error("Some modules have inconsistent states, some dependencies may be missing: %s", sorted(module_list))# STEP 3.6: apply remaining constraints in case of an upgraderegistry.finalize_constraints()# STEP 4: Finish and cleanup installationsif processed_modules:env = api.Environment(cr, SUPERUSER_ID, {})cr.execute("SELECT model from ir_model")for (model,) in cr.fetchall():if model in registry:env[model]._check_removed_columns(log=True)elif _logger.isEnabledFor(logging.INFO): # more an info that a warning..._logger.runbot("Model %s is declared but cannot be loaded! (Perhaps a module was partially removed or renamed)", model)# Cleanup orphan recordsenv['ir.model.data']._process_end(processed_modules)env.flush_all()for kind in ('init', 'demo', 'update'):tools.config[kind] = {}# STEP 5: Uninstall modules to removeif update_module:# Remove records referenced from ir_model_data for modules to be# removed (and removed the references from ir_model_data).cr.execute("SELECT name, id FROM ir_module_module WHERE state=%s", ('to remove',))modules_to_remove = dict(cr.fetchall())if modules_to_remove:env = api.Environment(cr, SUPERUSER_ID, {})pkgs = reversed([p for p in graph if p.name in modules_to_remove])for pkg in pkgs:uninstall_hook = pkg.info.get('uninstall_hook')if uninstall_hook:py_module = sys.modules['odoo.addons.%s' % (pkg.name,)]getattr(py_module, uninstall_hook)(cr, registry)env.flush_all()Module = env['ir.module.module']Module.browse(modules_to_remove.values()).module_uninstall()# Recursive reload, should only happen once, because there should be no# modules to remove next timecr.commit()_logger.info('Reloading registry once more after uninstalling modules')registry = odoo.modules.registry.Registry.new(cr.dbname, force_demo, status, update_module)cr.reset()registry.check_tables_exist(cr)cr.commit()return registry# STEP 5.5: Verify extended fields on every model# This will fix the schema of all models in a situation such as:# - module A is loaded and defines model M;# - module B is installed/upgraded and extends model M;# - module C is loaded and extends model M;# - module B and C depend on A but not on each other;# The changes introduced by module C are not taken into account by the upgrade of B.if models_to_check:registry.init_models(cr, list(models_to_check), {'models_to_check': True})# STEP 6: verify custom views on every modelif update_module:env = api.Environment(cr, SUPERUSER_ID, {})env['res.groups']._update_user_groups_view()View = env['ir.ui.view']for model in registry:try:View._validate_custom_views(model)except Exception as e:_logger.warning('invalid custom view(s) for model %s: %s', model, tools.ustr(e))if report.wasSuccessful():_logger.info('Modules loaded.')else:_logger.error('At least one test failed when loading the modules.')# STEP 8: save installed/updated modules for post-install tests and _register_hookregistry.updated_modules += processed_modules# STEP 9: call _register_hook on every model# This is done *exactly once* when the registry is being loaded. See the# management of those hooks in `Registry.setup_models`: all the calls to# setup_models() done here do not mess up with hooks, as registry.ready# is False.env = api.Environment(cr, SUPERUSER_ID, {})for model in env.values():model._register_hook()env.flush_all()
0、初始化数据库
这里判断数据库有没有被初始化,如果没有,就安装base模块
initialize_sys_path()force = []if force_demo:force.append('demo')models_to_check = set()with registry.cursor() as cr:# prevent endless wait for locks on schema changes (during online# installs) if a concurrent transaction has accessed the table;# connection settings are automatically reset when the connection is# borrowed from the poolcr.execute("SET SESSION lock_timeout = '15s'")if not odoo.modules.db.is_initialized(cr):if not update_module:_logger.error("Database %s not initialized, you can force it with `-i base`", cr.dbname)return_logger.info("init db")odoo.modules.db.initialize(cr)update_module = True # process auto-installed modulestools.config["init"]["all"] = 1if not tools.config['without_demo']:tools.config["demo"]['all'] = 1if 'base' in tools.config['update'] or 'all' in tools.config['update']:cr.execute("update ir_module_module set state=%s where name=%s and state=%s", ('to upgrade', 'base', 'installed'))
step 1、加载base模块
第一步就是加载base模块, 最后还加载了其他模块的语言包
SELECT model || '.' || name FROM ir_model_fields WHERE translate IS TRUE #原来pg使用|| 来拼接字符串的。registry._database_translated_fields = {row[0] for row in cr.fetchall()} # 这个写法也很有意思,简洁
# STEP 1: LOAD BASE (must be done before module dependencies can be computed for later steps)graph = odoo.modules.graph.Graph()graph.add_module(cr, 'base', force)if not graph:_logger.critical('module base cannot be loaded! (hint: verify addons-path)')raise ImportError('Module `base` cannot be loaded! (hint: verify addons-path)')if update_module and odoo.tools.table_exists(cr, 'ir_model_fields'):# determine the fields which are currently translated in the databasecr.execute("SELECT model || '.' || name FROM ir_model_fields WHERE translate IS TRUE")registry._database_translated_fields = {row[0] for row in cr.fetchall()} # processed_modules: for cleanup step after install# loaded_modules: to avoid double loadingreport = registry._assertion_reportloaded_modules, processed_modules = load_module_graph(cr, graph, status, perform_checks=update_module,report=report, models_to_check=models_to_check)load_lang = tools.config.pop('load_language')if load_lang or update_module:# some base models are used below, so make sure they are set upregistry.setup_models(cr)if load_lang:for lang in load_lang.split(','):tools.load_language(cr, lang)
控制台输出
2023-11-04 07:58:50,981 1340 INFO ? odoo.service.server: HTTP service (werkzeug) running on LAPTOP-AV3CF7SO:8069
2023-11-04 07:58:50,987 1340 INFO odoo2 odoo.modules.loading: loading 1 modules...
2023-11-04 07:58:51,008 1340 INFO odoo2 odoo.modules.loading: 1 modules loaded in 0.02s, 0 queries (+0 extra)
2023-11-04 07:58:51,154 1340 INFO odoo2 odoo.addons.base.models.ir_module: module base: loading translation file zh_CN for language zh_CN
2023-11-04 07:58:52,077 1340 INFO odoo2 odoo.addons.base.models.ir_module: module web: loading translation file zh_CN for language zh_CN
2023-11-04 07:58:52,256 1340 INFO odoo2 odoo.addons.base.models.ir_module: module base_setup: loading translation file zh_CN for language zh_CN
2023-11-04 07:58:52,282 1340 INFO odoo2 odoo.addons.base.models.ir_module: module bus: loading translation file zh_CN for language zh_CN
2023-11-04 07:58:52,295 1340 INFO odoo2 odoo.addons.base.models.ir_module: module web_tour: loading translation file zh_CN for language zh_CN
2023-11-04 07:58:52,304 1340 INFO odoo2 odoo.addons.base.models.ir_module: module mail: loading translation file zh_CN for language zh_CN
中间省略N行....
sql_constraint:cf.report.define.field
2023-11-04 07:58:54,087 1340 INFO odoo2 odoo.tools.translate: Skipped deprecated occurrence sql_constraint:cf.report.define
2023-11-04 07:58:54,087 1340 INFO odoo2 odoo.tools.translate: Skipped deprecated occurrence selection:cf.report.define,state
2023-11-04 07:58:54,094 1340 INFO odoo2 odoo.addons.base.models.ir_module: module estate: no translation for language zh_CN
2023-11-04 07:58:54,102 1340 INFO odoo2 odoo.addons.base.models.ir_module: module hx_base: no translation for language zh_CN
2023-11-04 07:58:54,115 1340 INFO odoo2 odoo.addons.base.models.ir_module: module hx_chp: no translation for language zh_CN
2023-11-04 07:58:54,122 1340 INFO odoo2 odoo.addons.base.models.ir_module: module hx_gift: no translation for language zh_CN
2023-11-04 07:58:54,129 1340 INFO odoo2 odoo.addons.base.models.ir_module: module hx_jixiao: no translation for language zh_CN
2023-11-04 07:58:54,136 1340 INFO odoo2 odoo.addons.base.models.ir_module: module hx_tsl: no translation for language zh_CN
2023-11-04 07:58:54,143 1340 INFO odoo2 odoo.addons.base.models.ir_module: module auth_totp: loading translation file zh_CN for
step 2、加载或者升级其他模块
# STEP 2: Mark other modules to be loaded/updatedif update_module:env = api.Environment(cr, SUPERUSER_ID, {})Module = env['ir.module.module']_logger.info('updating modules list')Module.update_list()_check_module_names(cr, itertools.chain(tools.config['init'], tools.config['update']))module_names = [k for k, v in tools.config['init'].items() if v]if module_names:modules = Module.search([('state', '=', 'uninstalled'), ('name', 'in', module_names)])if modules:modules.button_install()module_names = [k for k, v in tools.config['update'].items() if v]if module_names:modules = Module.search([('state', 'in', ('installed', 'to upgrade')), ('name', 'in', module_names)])if modules:modules.button_upgrade()env.flush_all()cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base'))Module.invalidate_model(['state'])
如果没有,这一步就跳过了
step 3、加载除了base之外的其他模块
1、分两个步骤完成,第一步加载所有已经安装的或者部分安装(需要升级),为第二步提供一个一致性的系统。第二步是安装新的模块。
我们在第一步中考虑了to_remove 的模块,因为他们是“已安装”模块的一部分, 他们将在step 6 去处理。
2、这里不得不循环处理,因为要处理模块之间的依赖关系
# STEP 3: Load marked modules (skipping base which was done in STEP 1)# IMPORTANT: this is done in two parts, first loading all installed or# partially installed modules (i.e. installed/to upgrade), to# offer a consistent system to the second part: installing# newly selected modules.# We include the modules 'to remove' in the first step, because# they are part of the "currently installed" modules. They will# be dropped in STEP 6 later, before restarting the loading# process.# IMPORTANT 2: We have to loop here until all relevant modules have been# processed, because in some rare cases the dependencies have# changed, and modules that depend on an uninstalled module# will not be processed on the first pass.# It's especially useful for migrations.previously_processed = -1# 循环加载处理相关模块while previously_processed < len(processed_modules):previously_processed = len(processed_modules)processed_modules += load_marked_modules(cr, graph,['installed', 'to upgrade', 'to remove'],force, status, report, loaded_modules, update_module, models_to_check)if update_module:processed_modules += load_marked_modules(cr, graph,['to install'], force, status, report,loaded_modules, update_module, models_to_check)# 处理需要升级的模块if update_module:# set up the registry without the patch for translated fieldsdatabase_translated_fields = registry._database_translated_fieldsregistry._database_translated_fields = ()registry.setup_models(cr)# determine which translated fields should no longer be translated,# and make their model fix the database schemamodels_to_untranslate = set()for full_name in database_translated_fields:model_name, field_name = full_name.rsplit('.', 1)if model_name in registry:field = registry[model_name]._fields.get(field_name)if field and not field.translate:_logger.debug("Making field %s non-translated", field)models_to_untranslate.add(model_name)registry.init_models(cr, list(models_to_untranslate), {'models_to_check': True})registry.loaded = Trueregistry.setup_models(cr)# check that all installed modules have been loaded by the registryenv = api.Environment(cr, SUPERUSER_ID, {})Module = env['ir.module.module']modules = Module.search(Module._get_modules_to_load_domain(), order='name')missing = [name for name in modules.mapped('name') if name not in graph]if missing:_logger.error("Some modules are not loaded, some dependencies or manifest may be missing: %s", missing)# STEP 3.5: execute migration end-scriptsmigrations = odoo.modules.migration.MigrationManager(cr, graph)for package in graph:migrations.migrate_module(package, 'end')# check that new module dependencies have been properly installed after a migration/upgradecr.execute("SELECT name from ir_module_module WHERE state IN ('to install', 'to upgrade')")module_list = [name for (name,) in cr.fetchall()]if module_list:_logger.error("Some modules have inconsistent states, some dependencies may be missing: %s", sorted(module_list))# STEP 3.6: apply remaining constraints in case of an upgraderegistry.finalize_constraints()
控制台输出:
2023-11-04 08:16:23,488 11076 INFO odoo2 odoo.modules.loading: loading 54 modules...
2023-11-04 08:16:23,882 11076 WARNING odoo2 odoo.api.create: The model odoo.addons.hx_chp.models.change_point is not overriding the create method 2023-11-04 08:16:23,944 11076 WARNING odoo2 odoo.api.create: The model odoo.addons.hx_tsl.models.hx_tsl_info is not overriding the create method in batch
2023-11-04 08:16:24,292 11076 WARNING odoo2 odoo.api.create: The model odoo.addons.cfprint.models.cfprint_server_user_map is not overriding the create method in batch
2023-11-04 08:16:25,047 11076 WARNING odoo2 odoo.api.create: The model odoo.addons.cf_report_designer.models.data_model_3 is not overriding the create method in batch
2023-11-04 08:16:25,069 11076 WARNING odoo2 odoo.api.create: The model odoo.addons.cf_report_designer.models.data_model_4 is not overriding the create method in batch
2023-11-04 08:16:25,071 11076 WARNING odoo2 odoo.api.create: The model odoo.addons.cf_report_designer.models.data_model_4 is not overriding the create method in batch
2023-11-04 08:16:25,416 11076 INFO odoo2 odoo.modules.loading: 54 modules loaded in 1.93s, 0 queries (+0 extra)
step 4、完成并且清理安装过程
基本就是一些善后过程,正常情况下不会执行
# STEP 4: Finish and cleanup installationsif processed_modules:env = api.Environment(cr, SUPERUSER_ID, {})cr.execute("SELECT model from ir_model")for (model,) in cr.fetchall():if model in registry:env[model]._check_removed_columns(log=True)elif _logger.isEnabledFor(logging.INFO): # more an info that a warning..._logger.runbot("Model %s is declared but cannot be loaded! (Perhaps a module was partially removed or renamed)", model)# Cleanup orphan recordsenv['ir.model.data']._process_end(processed_modules)env.flush_all()for kind in ('init', 'demo', 'update'):tools.config[kind] = {}
step 5、卸载相关模块
SELECT name, id FROM ir_module_module WHERE state=%s", ('to remove',)
如果配置了uninstall_hook,要在这里执行。 然后调用module_uninstall()方法来卸载
Module.browse(modules_to_remove.values()).module_uninstall()
卸载完成之后,刷新注册表。
5.5 是要处理一些模型之间的依赖关系。
# STEP 5: Uninstall modules to removeif update_module:# Remove records referenced from ir_model_data for modules to be# removed (and removed the references from ir_model_data).cr.execute("SELECT name, id FROM ir_module_module WHERE state=%s", ('to remove',))modules_to_remove = dict(cr.fetchall())if modules_to_remove:env = api.Environment(cr, SUPERUSER_ID, {})pkgs = reversed([p for p in graph if p.name in modules_to_remove])for pkg in pkgs:uninstall_hook = pkg.info.get('uninstall_hook')if uninstall_hook:py_module = sys.modules['odoo.addons.%s' % (pkg.name,)]getattr(py_module, uninstall_hook)(cr, registry)env.flush_all()Module = env['ir.module.module']Module.browse(modules_to_remove.values()).module_uninstall()# Recursive reload, should only happen once, because there should be no# modules to remove next timecr.commit()_logger.info('Reloading registry once more after uninstalling modules')registry = odoo.modules.registry.Registry.new(cr.dbname, force_demo, status, update_module)cr.reset()registry.check_tables_exist(cr)cr.commit()return registry# STEP 5.5: Verify extended fields on every model# This will fix the schema of all models in a situation such as:# - module A is loaded and defines model M;# - module B is installed/upgraded and extends model M;# - module C is loaded and extends model M;# - module B and C depend on A but not on each other;# The changes introduced by module C are not taken into account by the upgrade of B.if models_to_check:registry.init_models(cr, list(models_to_check), {'models_to_check': True})
step 6、确认每个模型相关的视图
# STEP 6: verify custom views on every modelif update_module:env = api.Environment(cr, SUPERUSER_ID, {})env['res.groups']._update_user_groups_view()View = env['ir.ui.view']for model in registry:try:View._validate_custom_views(model)except Exception as e:_logger.warning('invalid custom view(s) for model %s: %s', model, tools.ustr(e))if report.wasSuccessful():_logger.info('Modules loaded.')else:_logger.error('At least one test failed when loading the modules.')
控制台输出
2023-11-04 08:35:43,841 11076 INFO odoo2 odoo.modules.loading: Modules loaded.
step 8、保存安装或者升级的视图
为了post-install测试 和调用_register_hook, step7 哪去了????
# STEP 8: save installed/updated modules for post-install tests and _register_hookregistry.updated_modules += processed_modules
step 9、调用_register_hook
对每个model模型调用_register_hook,每次启动的时候都会调用,能干什么呢?
# STEP 9: call _register_hook on every model# This is done *exactly once* when the registry is being loaded. See the# management of those hooks in `Registry.setup_models`: all the calls to# setup_models() done here do not mess up with hooks, as registry.ready# is False.env = api.Environment(cr, SUPERUSER_ID, {})for model in env.values():model._register_hook()env.flush_all()
models.py
def _register_hook(self):""" stuff to do right after the registry is built """def _unregister_hook(self):""" Clean up what `~._register_hook` has done. """
_register_hook 有什么用?
可以在模块加载完之后动态修改模型的一些属性值。
比如修改_rec_name
def _register_hook(self):setattr(type(self),'_rec_name', 'myname')
安装模块的时候也会执行load_modules函数重新加载所有的模块,如果你希望你的逻辑只有在启动的时候执行而不是安装模块的时候执行,在context中有个变量可以区分。
哪个变量?
99%的人还看了
相似问题
- go语言实现高性能自定义ip管理模块(ip黑名单)
- 【Django使用】4大模块50页md文档,第4篇:Django请求与响应和cookie与session
- 【python学习】基础篇-常用模块-pickle模块:序列化和反序列化
- #gStore-weekly | gAnswer源码解析 调用NE模块流程
- 【前端知识】Node——events模块的相关方法
- 使用Python的turtle模块绘制玫瑰花图案(含详细Python代码与注释)
- 【ES6标准入门】JavaScript中的模块Module语法的使用细节:export命令和imprt命令详细使用,超级详细!!!
- SpringBoot学习笔记-配置MySQL与实现注册登录模块(中)
- 一个奇怪的蓝牙模块分析记录
- 前端JS模块化对外暴露的三种方法
猜你感兴趣
版权申明
本文"odoo启动-加载模块(load_modules)":http://eshow365.cn/6-35132-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!
- 上一篇: SLAM_语义SLAM相关论文
- 下一篇: 链表经典面试题之一讲