栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

【ODOO14】odoo中的数据库迁移管理

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【ODOO14】odoo中的数据库迁移管理

odoo中的数据库迁移管理 前言

在最近odoo开发时,出现了模型结构变更导致数据库升级失败的问题。在Boss的指导下,发现了那个在Django中使用了无数次的关键字migrate。原来odoo也提供了数据库迁移脚本工具,这个工具很简单,从开发的角度来说,有些地方的处理可以说很粗糙。但按照一定的规则去做odoo开发,不管的是大版本之间的迁移,还是小版本之间的迁移,这个工具起到的效果还是很棒的。

odoo 提供了 MigrationManager 类来管理数据库迁移。脚本路径:odoo/modules/migration.py。

文档环境
  • version: 14.0
源码分析 MigrationManager

在odoo中,数据库迁移的实现是通过MigrationManager类实现的,这里分析下odoo/modules/migration.py这个文件。

_init_(self, cr, graph)
def __init__(self, cr, graph):
    self.cr = cr
    self.graph = graph
    self.migrations = defaultdict(dict)
    self._get_files()

该方法为MigrationManager的构造方法。它接受两个参数:

  • cr:当前数据库游标(db.cursor()),供后续处理数据库迁移操作数据库使用。
  • graph:要加载的模块节点图,供后续处理数据库迁移判断状态使用。
_get_files(self)

该方法在实例化MigrationManager时被调用,其作用是通过遍历模块节点图,获取每个模块的数据库迁移脚本文件路径,初始化到migrations中。

for pkg in self.graph:
    if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade' or getattr(pkg, 'load_state', None) == 'to upgrade'):
        continue

        self.migrations[pkg.name] = {
            'module': get_scripts(get_resource_path(pkg.name, 'migrations')),
            'module_upgrades': get_scripts(get_resource_path(pkg.name, 'upgrades')),
            'upgrade': get_scripts(_get_upgrade_path(pkg.name)),
        }

另外在该方法中提供了以下两个闭包:

  • _get_upgrade_path(pkg):该闭包在odoo/odoo/upgrade和odoo/odoo/addons/base/maintenance/migrations文件夹下扫描,如果在任一文件夹下找到以给定模块名命名的子文件夹,则返回子文件夹完整路径,否则返回None。供get_scripts闭包使用。
  • get_scripts(path):该闭包返回给定路径下后缀为.py的文件路径列表。
migrate_module(package, state)

该方法migrate_module,是处理数据库迁移的核心方法,接受以下两个参数:

  • package: 即模块或插件名。
  • stage:即处理阶段。数据库迁移分了以下三个阶段,用于在不同时机处理数据库迁移操作:
    • pre:在模块初始化之前执行。migrate_module(package, 'pre')
    • post:在模块初始化之后执行。migrate_module(package, 'post')
    • end:在所有模块更新后运行。migrate_module(package, 'end')

该方法提供了三个闭包方法

  • convert_version(version):该闭包将给定版本字符串简单处理并返回(迁移脚本中version的处理)。
  • _get_migration_versions(pkg, stage):该闭包处理并返回数据库迁移版本号码。
  • get_migration_files(pkg, version, stage):该闭包通过处理给定模块、给定版本和给定处理阶段,获取相应迁移脚本文件的完整路径。
脚本流程

当实例数据库的模型注册表发生变更时,会通过load_modules方法重新加载实例中的模块或插件,在此加载过程中执行了数据库迁移功能,即调用了MigrationManager.migrate_module方法。

核心处理流程如下:

  1. 数据库迁移条件检查:判断给定package对应的模块状态是否符合迁移条件,若不符合,不会继续以下步骤。
  2. 获取并格式化迁移前模块版本号,该版本号为__manifest__.py文件中的version值(odoo处理规则)。
  3. 获取并格式化给定模块的当前迁移版本号。
  4. 比较迁移前模块版本号和给定模块的当前迁移版本号,如果当前迁移版本号比迁移前模块版本号小,不会继续以下步骤。
  5. 获取给定模块对应的模块文件夹下的迁移脚本文件路径。
  6. 执行迁移脚本文件中的逻辑处理。
odoo处理version规则

manifest 文件中的版本号version的值,如果不是以当前主版本号(即服务版本号,比如14.0)开头,会被认定为模块版本号。但odoo会处理成以当前主版本号(即服务版本号,比如14.0)开头的完整版本号,存储到数据库。比如:

  • 在服务版本为14.0时,12.0.0.1会被认定为模块版本号,并最终被处理的完整版本号为14.0.12.0.0.1
  • 在服务版本为14.0时,0.1会被认定为模块版本号,并最终被处理的完整版本号为14.0.0.1
  • 在服务版本为14.0时,14.0.0.1会被认定为完整版本号,不会被处理。

比较好的实践是开发团队间约定一套版本规则,尽量在开发时,书写完整的版本号。避免出现不必要的麻烦。

迁移脚本中version的处理

该处理在convert_version中实现,处理时根据判断给定版本号字符串中.的数量处理出版本号,当数量>=2时,直接返回。否则,将当前主版本号(比如14.0)作为前缀拼接到给定版本号字符串返回。比如:

  • 给定版本字符串为0.0.1,将直接返回0.0.1。
  • 给定版本字符串为0.1,将直接返回14.0.0.1。

在获取迁移脚本路径时,会根据返回的版本字符串扫描文件夹,如果没找到,迁移程序就不会执行。既然如此,还是建议开发团队间约定一套版本规则,尽量在开发时,书写完整的版本号。避免出现不必要的麻烦。

使用规范

使用此数据库迁移功能,需要遵循以下规则,约定此文档对应的主版本(即服务版本)为14.0:

  • 迁移管理代码遵循以下目录树结构:

        module_name
            |-- migrations
                |-- 1.0       													# 在更新版本为 14.0.1.0 时被处理,但前列建议写全版本号                      
                |   |-- pre-update_table_x.py
                |   |-- pre-update_table_y.py
                |   |-- post-create_plop_records.py
                |   |-- end-cleanup.py
                |   `-- README.txt                      # 不会被处理
                |-- 13.0.1.1                            # 不会被处理(只在 13.0 中被处理)
                |   |-- pre-delete_table_z.py
                |   `-- post-clean-data.py
                |-- 0.0.0                               # 在所有版本被处理
                |   `-- end-invariants.py               
                `-- foo.py                              # 不会被处理
    

    在需要执行数据库迁移的模块根目录下必须创建名为migrations的文件夹,其中包含按版本划分的文件夹。

    • 版本文件夹名可以不含服务版本号,只含模块版本号。

      比如:1.0。如果没有主版本数据库迁移需求(比如13.0升级到14.0),可以这样命名。因为程序处理会自动拼接主版本号。

    • 版本文件夹名也可以即含服务版本号,有含模块版本号。

      比如:13.0.1.1。

    • 版本文件夹名还可以是一个特殊号码:0.0.0,此文件夹下的迁移文件将在任何版本更改时运行。

  • 迁移处理文件必须是以pre-、post-或end-开头的Python文件。

    • pre-在模块初始化之前执行。
    • post-在模块初始化之后执行。
    • end-在所有模块更新后运行。
  • 迁移文件必须是包含migrate(cr,installed_version)函数的python文件。

注意:在 pre 阶段,0.0.0 脚本首先运行,而在 post 和 end 中,0.0.0 脚本最后运行。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/923465.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号