本章代码可在原作者github下载

使用外部ID及命名空间

外部ID及XML ID用于标记记录。到目前为止,我们在视图、菜单及动作中接触了XML IDs。本节我们将进一步了解什么是XML ID。

步骤

  1. 更新my_library模块中的manifest文件
'data': [
'data/data.xml',
],
  1. 创建一本书
<record id="book_cookbook" model="library.book">
<field name="name"> Odoo 14 Development Cookbook </ field>
</record>
  1. 修改公司的名称
<record id="base.main_company" model="res.company">
<field name="name">Packt publishing</field>
</record>

原理

XML ID是单条记录的引用。IDs是ir.model.data模型。这个模型包括模型的名称、ID及其他内容。

每次我们应用XML ID,odoo会检查字符串中是否包含命名空间。如果没有,它会添加当前模块名作为命名空间。并以此在ir.model.data中查找是否存在目标记录。如果存在,所列字段将会被更新。若不存在,将会创建。

重要提醒

除了更改其他模块定义的记录外,部分数据的一个广泛应用是使用快捷方式元素以方便的方式创建记录,并在该记录上写入一个字段,而快捷方式元素不支持该字段:

<act_window id="my_action" name="My action" model="res.partner" />
<record id="my_action" model="ir.actions.act_ window">
<field name="auto_search" eval="False" /> </record>

ref函数也将会添加当前模块作为命名空间。但如果生成的XML ID并不存在,将会报错。

小贴士

系统中的XML ID可在Settings|Technical|Sequence & Identifiers|External Identifiers中查看。

更多

我们后面将会需要在python代码中使用XML ID。可通过self.env.ref(XMLID)函数引用目标记录。

我们可以查找系统中任何数据的XML ID。如下:

通过xml文件载入数据

步骤

  1. 添加data/demo.xml文件
'demo': [
'data/demo.xml',
],
  1. 添加内容
<odoo>
<record id="author_pga" model="res.partner">
<field name="name">Parth Gajjar</field> </record>
<record id="author_af" model="res.partner">
<field name="name">Alexandre Fayolle</field>
</record>
<record id="author_dr" model="res.partner">
<field name="name">Daniel Reis</field>
</record>
<record id="author_hb" model="res.partner">
<field name="name">Holger Brunn</field>
</record>
<record id="book_cookbook" model="library.book">
<field name="name">Odoo Cookbook</field>
<field name="short_name">cookbook</field>
<field name="date_release">2016-03-01</field>
<field name="author_ids"
eval="[(6, 0, [ref('author_af'),
ref('author_dr'), />
ref('author_hb')])]"
<field name="publisher_id" ref="res_partner_ packt" />
</record>
</odoo>
  1. 在manifest添加data/data.xml
'data': [
'data/data.xml', ...
],
  1. 添加内容
<odoo>
<record id="res_partner_packt" model="res.partner">
<field name="name">Packt Publishing</field>
<field name="city">Birmingham</field>
<field name="country_id" ref="base.uk" />
</record>
</odoo>

原理

数据xml文件通过标签创建新记录。有两个强制属性,id和model。id,是数据的外部ID。model,是数据属于哪个模型。通过标签添加字段的值。

有两种方式将data的xml文件注册到模块中。分别是data和demo键。data键是在每次在加载模块的时候都会更新。demo是只有在启动了demo数据的时候才会加载。

步骤1,我们通过demo键注册了data xml文件。因为我们使用了demo的键,因此只有我们在启用了demo的时候才会加载。

步骤2,元素包含字符串值。如果你需要传文件的内容,可以通过在field中的file属性传递文件名。

为了设置引用,有两种方式。最简单的是通过ref属性,作用于many2one字段,通过引用目标记录的XML ID实现。对于one2many及many2many字段,我们使用eval属性。这是一通用属性,可以通过python代码计算字段值。比如为date字段赋值strftime('%Y-01-01')。X2many字段可被三元元组赋值,第一个元素是决定计算的方式。在eval属性中,我们通过ref获取XML ID数据的数据库ID。三元元组关系如下:

  • (0, False, {'key':value}): 创建一个新的记录并关联到目标模型上。由于这些记录没有XML ID,因此可能会出现重复的情况。因此,建议在创建记录的时候通过各自的模型进行创建。
  • (1, id, {'key':value}): 这会在一条已经存在的记录上执行写操作。同上,我们应该避免如此使用。
  • (2, id, False): 从数据库删除关联记录(id),第三个元素忽略。
  • (3, id, False): 解绑ID为id的关联记录,并不从数据库中删除。
  • (4, id, False): 添加关联一个在数据库中已经存在的记录。这是最常使用的。
  • (5, False, False): 取消所有的关联记录。
  • (6, False, [id, ...]): 取消所有关联记录,并关联新的记录。

    步骤3、4,类似1、2。

重要提醒

需关注数据文件中记录的添加的先后顺序。这也是为什么你需要检查模块在空数据库中安装的情况,因为在开发的过程中,可能已经添加了相关数据。

更多

record基本上可以完成所有的场景,还有一些简写方式可便捷的创建数据。比如,菜单、模板、窗体动作。

field元素还可以执行function元素,执行相应的函数。

使用noupdate及forcecreate标识

大不多模块有不同类型的数据。一些数据是为了模块能够正常运行,一些不应该被用户修改,大多数数据可以被用户修改,只是为了方便,通常情况下会通过数据文件预加载。本节将详细讨论不同类型的数据。首先我们会在一个已经存在的记录中某个字段写入数据,然后我们将在模块更新重复创建一条数据。

步骤

我们可以在元素或元素中设置不同的属性,以控制数据加载时不同的行为。

  1. 在初始化的时候添加一条出版商,但是在后续的模块升级中并不更新。但如果该记录被删除,那么将会被重新创建。
<odoo noupdate="1">
<record id="res_partner_packt" model="res.partner">
<field name="name">Packt publishing</field>
<field name="city">Birmingham</field>
<field name="country_id" ref="base.uk"/>
</record>
</odoo>
  1. 添加一条图书种类的记录,但是该记录在模块升级的时候并不进行修改,在数据被删除后也不会再次创建。forcecreate="false"
<odoo noupdate="1">
<record id="book_category_all" model="library.book. category" forcecreate="false">
<field name="name">All books</field>
</record>
</odoo>

原理

有noupdate属性,该属性将最为新纪录创建时的列。

当odoo安装模块的时候,无论noupdate为false还是true,所有的记录会被写入。但是当对模块进行升级的时候,将会检查已经存在的XML ID记录是否有noupdate标志位。如果设置了,将会忽略本次的数据写入。如果有问题的记录被用户删除,情况就不是这样了,这就是为什么您可以通过将记录上的forceccreate标志设置为false来强制不在更新模式下重新创建noupdate记录。

重要提醒

在odoo8及之前的版本中,你将会看到标签,内部包含标签及其他标签。这种语法当前依旧有效,但已经被启用了。现在、、有相似的效果。他们都将包含xml数据。

更多

如果你想在右noupdate标志位的情况下更新数据,那么你可以在运行odoo服务的时候添加--init=your_addon 或者 -i your_addon参数。这将强制重载数据。请注意,如果模块绕过了XML ID机制(例如,通过标签调用Python代码创建记录),这可能会导致双记录和相关的安装错误。

以上操作方式,将可能绕过noupdate标志位,一定要确保这是你想要的效果。另一个解决方案是编写迁移脚本,将在 下面几节中介绍。

参考

odoo也使用XML IDs跟踪在模块更新的时候那些数据将被删除。如果一条记录在模块更新前已经有了XML ID,但是在更新的时候模块中又没有该XML ID的记录情况,那么该记录将被认为过时了,将会被删除。

通过CSV载入数据库

通过XML文件可以满足很多场景,但是这种格式在需要处理大量数据的时候并不是太方便。通过CSV格式的另一个优势是导出数据的时候也是采用CSV的格式。

步骤

权限控制(access-control lists ACL)就是通过CSV实现导入的。

  1. 添加security/ir.model.access.csv文件
'data': [
...
'security/ir.model.access.csv',
],
  1. 添加图书访问权限
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
acl_library_book_user,ACL for books,model_library_book,base.group_user,1,0,0,0

原理

你只需要将需要的数据文件写在manifest的data列表中即可。odoo会根据文件的后缀是哪种类型的文件。csv文件的文件名必须是model的名称。比如,ir.model.access.cs。

对于标量值,可以使用带引号的字符串(如果需要,因为字符串本身包含引号或逗号)或不带引号的字符串。

当使用CSV文件编写many2one字段时,Odoo首先尝试将列值解释为XML ID。如果没有点,Odoo将当前模块名添加为名称空间,并在ir.model.data中查找结果。如果失败,将调用模型的name_search函数,并将列的值作为参数,第一个返回的结果将获胜。如果同样失败,则认为该行无效,并引发Odoo错误。

重要提醒

从CSV文件读取的数据总是noupdate=False,而且没有什么方便的方法来解决这个问题。这意味着您的附加组件的后续更新将总是覆盖用户所做的可能更改。

如果你需要加载大量数据,而noupdate对你来说是个问题,那就从init钩子加载CSV文件。

更多

用CSV文件导入one2many和many2many字段是可能的,但有点棘手。通常,您最好分别创建记录,然后使用XML文件设置关系,或者使用第二个CSV文件设置关系。

如果您确实需要在同一个文件中创建相关记录,请对列进行排序

使所有标量字段都在左边,链接模型的字段在右边,列头由链接字段的名称和链接模型的字段组成,用冒号分隔:

"id","name","model_id:id","perm_read","perm_read", "group_ id:name"
"access_library_book_user","ACL for books","model_library_ book",1,
"my group"

这会创建一个名为my group的组;通过向右侧添加列,可以在组记录中写入更多字段。如果需要链接多个记录,请重复该行,并根据需要更改右边的列。由于Odoo用前一行的值填充空列,所以不需要复制所有数据——只需添加即可

为您想要填充的链接模型的字段保存空值的一行。对于x2m字段,只需列出要链接的记录的XML id。

插件的更新及数据迁移

编写附加模块时选择的数据模型可能有一些缺陷,因此可能需要在附加模块的生命周期中对其进行调整。为了在没有很多破解的情况下实现这一点,Odoo支持在附加模块中进行版本控制,并在必要时运行迁移。

步骤

我们假设在模块的早期版本中,date_release字段为一个字符栏,人们可以在那里写下他们认为合适的日期。我们现在意识到我们需要这个字段来进行比较和聚合,这就是为什么我们要将它的类型更改为Date。

  1. 修改版本信息
'version': '13.0.1.0.1',
  1. 在migration /13.0.1.0.1/pre- migration .py中提供预迁移代码:
def migrate(cr, version):
cr.execute('ALTER TABLE library_book RENAME COLUMN date_release TO date_release_char')
  1. 在migration /13.0.1.0.1/post- migration .py中提供迁移后的代码:
from odoo import fields
from datetime import date
def migrate(cr, version):
cr.execute('SELECT id, date_release_char FROM library_book')
for record_id, old_date in cr.fetchall():
# check if the field happens to be set in Odoo's internal
# format
new_date = None
try:
new_date = fields.Date.to_date(old_date)
except ValueError:
if len(old_date) == 4 and old_date.isdigit():
# probably a year
new_date = date(int(old_date), 1, 1)
if new_date:
cr.execute('UPDATE library_book SET date_release=%s',(new_date,))

如果没有这些代码,Odoo就会将旧的date_release列重命名为date_release_moved,并创建一个新的列,因为不存在从字符字段到日期字段的自动转换。从用户的角度来看,date release中的数据将会消失。_

原理

迁移只在不同版本之间运行。在每次更新期间,Odoo将更新时清单中的版本号写入ir_module_模块表。版本号的前缀是Odoo的主要版本和次要版本

如果版本号有三个或更少的组件。在前面的示例中,我们显式地命名了Odoo的主版本和次版本,这是一种很好的做法,但是值1.0.1也会有同样的效果,因为在内部,Odoo用自己的主版本号和次版本号作为附加组件的短版本号前缀。通常,使用长表示法是一个好主意,因为您可以一眼看出插件是针对哪个版本的Odoo的。


这两个迁移文件只是不需要在任何地方注册的代码文件。当更新一个附加组件时,Odoo会比较该附加组件的版本(如ir_module_module中所示)与该附加组件清单中的版本。如果清单的版本更高(在添加Odoo的主版本和次版本之后),这个插件的migrations文件夹将会

搜索它,以查看它是否包含之间的版本(直到并包括当前更新的版本)的文件夹.


然后,在找到的文件夹中,Odoo搜索名称以pre-开头的Python文件,加载它们,并期望它们定义一个名为migrate的函数,该函数有两个参数。调用该函数时,数据库游标作为第一个参数,当前安装的版本作为第二个参数。这发生在Odoo查看附加组件定义的其余代码之前,因此您可以假设与前一个版本相比,您的数据库布局没有任何变化。

在所有预迁移函数成功运行之后,Odoo加载模型和插件中声明的数据,这可能导致数据库布局的更改。我们在预迁移中重新命名了date_release。 Odoo将使用该名称创建一个新列,但使用正确的数据类型。

之后,使用相同的搜索算法,将搜索迁移后的文件,并在找到后执行。在我们的例子中,我们需要查看每一个值,看看我们是否能从中得到有用的东西;否则,我们将数据保留为NULL。如果不是绝对必要,不要编写遍历整个表的脚本;在这种情况下,我们会写一个非常大的、不可读的SQL开关。

重要提醒

如果只是想重命名列,则不需要迁移脚本。在这种情况下,可以将相关字段的oldname参数设置为该字段的原始列名;然后,Odoo负责自己的重命名。

更多

在迁移前和迁移后的步骤中,您都只能访问光标,如果您习惯了Odoo环境,这就不太方便了。在这个阶段使用模型可能会导致意想不到的结果,因为在预迁移步骤中,附加组件的模型还没有加载,而且在迁移后步骤中,依赖于当前附加组件的附加组件定义的模型也还没有加载。然而,如果这对你来说不是问题,或者因为你想使用一个你的附加组件没有触及的模型,或者一个你知道这个问题不是问题的模型,你可以通过编写以下代码来创建你习惯的环境:

from odoo import api, SUPERUSER_ID
def migrate(cr, version):
env = api.Environment(cr, SUPERUSER_ID, {})
# env holds all currently loaded models

参考

在编写迁移脚本时,您经常会遇到重复的任务,例如如检查列或表是否存在,重命名事物,或将一些旧值映射到新值。在这里重复工作是令人沮丧和容易出错的;如果你能负担得起额外的依赖性,可以考虑使用https://github.com/OCA/openupgradelib。

通过xml文件删除数据

通过xml文件调用方法

【odoo14】第六章、管理模块数据的更多相关文章

  1. python 教程 第六章、 模块

    第六章. 模块 1) 模块 sys模块 字节编译的.pyc文件,优化编译后生成pyo文件 2) from..import语句 import sys print 'The command line ar ...

  2. 数据库系统第六章【关系数据理论】(B站视频)

    目录 数据库系统第六章[关系数据理论](B站视频) 一.前言 二.规范化 函数依赖 三种分类 如何确定函数依赖? 平凡函数依赖vs非平凡函数依赖 完全函数依赖vs部分函数依赖 传递函数依赖 码 超码 ...

  3. 第六章、Struts2数据校验

    一.三种实现方式 ① 用validate()方法实现数据校验 继承ActionSupport类,该类实现了Validateable接口,该接口中定义了一个validate()方法,在自定义的Actio ...

  4. 第六章 管理类型(In .net4.5) 之 创建类型

    1. 概述 本章内容包括 C#5中如何更好的创建类型以及如何扩展现有类型. 2. 主要内容 2.1 如何选择类型 C#类型系统包括三种类型:值类型.引用类型.指针类型.(指针类型用于非托管代码,很少使 ...

  5. 《mysql必知必会》学习_第六章_20180730_欢

    第六章<过滤数据> P35 1. select prod_name,prod_price from products where prod_price=2.5; 2.select prod ...

  6. 为什么我要放弃javaScript数据结构与算法(第六章)—— 集合

    前面已经学习了数组(列表).栈.队列和链表等顺序数据结构.这一章,我们要学习集合,这是一种不允许值重复的顺序数据结构. 本章可以学习到,如何添加和移除值,如何搜索值是否存在,也可以学习如何进行并集.交 ...

  7. 【odoo14】第二章、管理odoo实例

    本章主要介绍肖odoo实例添加用户自定义的模块.你可以从多个路径载入模块.但是建议你将自己的模块儿放在特定的目录当中,避免与odoo的核心模块混淆. 在这一章节,中我们主要涉及以下内容: 配置插件路径 ...

  8. Laxcus大数据管理系统2.0(8)- 第六章 网络通信

    第六章 网络通信 Laxcus大数据管理系统网络建立在TCP/IP网络之上,从2.0版本开始,同时支持IPv4和IPv6两种网络地址.网络通信是Laxcus体系里最基础和重要的一环,为了能够利用有限的 ...

  9. CentOS6安装各种大数据软件 第六章:HBase分布式集群的配置

    相关文章链接 CentOS6安装各种大数据软件 第一章:各个软件版本介绍 CentOS6安装各种大数据软件 第二章:Linux各个软件启动命令 CentOS6安装各种大数据软件 第三章:Linux基础 ...

随机推荐

  1. 牛客网多校第3场 C-shuffle card 【splay伸展树】

    题目链接:戳这里 转自:戳这里 关于splay入门:戳这里 题意:给n个数,进行m次操作,每次都从n个数中取出连续的数放在最前面. 解题思路:splay的区间操作. 附代码: 1 #include&l ...

  2. TCP之“3次握手,4次挥手”问题——实例分析

    上一篇我们分析了三次握手和四次握手的过程,但是理论分析难免枯燥难懂,下面这篇我们来看一个例子,就能更好地理解tcp链接了. 我们可以通过网络抓包的查看具体的流程: 比如我们服务器开启9502的端口.使 ...

  3. matplotlib 图标显示中文

    matplotlib 显示中文 Method_1: # 添上: plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 plt.rcPara ...

  4. 买车交税 All In One

    中国买车交税 All In One 消费税 增值税 车辆购置税 车船税 关税 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问! 原 ...

  5. short URL 短网址实现原理剖析

    short URL 短网址实现原理剖析 意义,简短便于分享,避免出现超长 URL 的字符长度限制问题 原理分析, 使用 HashMap 存储对应的映射关系 (长度不超过7的字符串,由大小写字母加数字共 ...

  6. LeetCode Binary Search All In One

    LeetCode Binary Search All In One Binary Search 二分查找算法 https://leetcode-cn.com/problems/binary-searc ...

  7. React Hooks 实现一个计时器组件

    React Hooks 实现一个计时器组件 useEffect https://reactjs.org/docs/hooks-reference.html#useeffect import React ...

  8. HTTP vs HTTP/2 vs HTTP/3 (QUIC)

    HTTP vs HTTP/2 vs HTTP/3 (QUIC) Nginx HTTP/1.1 HTTP/2 HTTP/3 (QUIC) HTTPS 计算机网络协议 OSI 协议簇 (7) TCP/IP ...

  9. taro router

    taro router https://nervjs.github.io/taro/docs/router.html bug import Taro, { Component, Config } fr ...

  10. Flutter: 粘贴板

    文档 import 'package:flutter/services.dart'; /// 把文本复制进入粘贴板 Clipboard.setData(ClipboardData(text: &quo ...