IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 【ODOO14】odoo中的数据库迁移管理 -> 正文阅读

[Python知识库]【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/upgradeodoo/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 脚本首先运行,而在 postend 中,0.0.0 脚本最后运行。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-05-24 18:07:23  更:2022-05-24 18:08:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:10:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码