【转载】odoo技术开发白皮书 第一部分 第三章 基本字段

转载:http://book.odoomommy.com/chapter1/README3.html

第三章 基本字段

上一章,我们介绍了如何从无到有地创建一个模块,本篇将介绍Odoo中常见得几种字段类型。

字段类型

由于Odoo使用了自己编写的ORM框架,因此它有着自己的一套与数据库映射的关系逻辑,简单地说就是由简单字段关系和复杂字段关系组成的。简单的字段关系比如Char,Integer,Float等,复杂字段关系如Many2one,Many2many等。下面就常见的几种字段类型进行简要的介绍。

通用字段属性

有些属性是字段共同拥有的,如下表:

属性名解释
name字段名
model_name模型名称
store是否存储在数据库中(默认True)
index字段在数据库中是否索引(默认False)
manual是否为自定义字段(默认False)
default字段的默认值
string字段的标签值
help帮助提示的值
readonly是否只读(默认False)
required是否必填(默认False)
states根据state设置reaonly和required属性
groups可以访问该字段的组的xmlid
related_sudo字段是否应该作为admin来访问

Char

字符类型,对应数据库中varchar类型,除了通用类型外接收另外两个参数:

  • size: 字符长度,超出的长度将被截断
  • trim: 默认True,是否字段值应该被去空白。

Text

文本类型,对应数据库中的text类型,不限长度,没有额外的参数。

Html

Html类型,用于存储一段HTML代码,对应数据库中的text类型,接收下面几个参数:

  • sanitize:是否过滤安全字符(默认True)
  • sanitize_tags: 是否过滤的html标签(只接收白名单列表标签,默认True)
  • sanitize_attributes: 是否过滤的html属性(只接收白名单列表属性,默认True)
  • sanitize_style: 是否过滤style属性(默认False)
  • strip_style: 是否去除style属性中的空白(默认False)
  • strip_classes:是否去除class属性中的空白(默认False)

Date

日期类型,对应于数据库中的date类型,该字段包括如下几个特有方法:

  • today: 当前日期
  • context_today: 返回客户端时区的当前时间
  • to_date: 将时间值转换为date类型的时间
  • to_string: 将时间值转为文本

例如我们想要给某个日期字段设置默认的属性为当天,那么可以像下面这样写:

date_start = fields.Date("开始日期",default=fields.Date.today())

Datetime

时间类型,对应于数据库中的timestamp类型,该字段包括如下几个特有方法:

  • now: 当前时间
  • today: 当前日期
  • context_timestamp: 客户端时区的当前时间戳
  • to_datetime:将时间值转换成datetime类型
  • to_string: 将时间值转成文本

假如我们想要给某个时间字段设置默认当前时间,那么可以像下面这样写:

date_start = fields.Datetime("开始时间",default=fields.Datetime.now())

Binary

二进制文件类型,接收三个参数:

  • prefetch: 默认False
  • context_dependent:默认True
  • attachment:默认True,是否作为附件存储

二进制文件作为附件存储时存在服务器指定的文件夹路径中,否则存在数据库中,对应的数据库类型为bytea.

图片类型的字段在odoo中亦是使用Binary字段存储的,只不过视图渲染时使用了image部件。

二进制字段通常以base64编码的形式存储在数据库中,因此在展示时,需要将base64进行解码输出。另外,二进制文件在form表单中只读状态下表现为下载按钮,但不包含原始的文件名。如果想要显示文件名,需要使用另外一字段将文件名存储起来。可参考如下代码:

<field name="xls" filename="xls_name"/>
<field name="xls_name" invisible="1"/>

关于二进制字段更多的内容,参考第二部分的二进制与附件一章。

Selection

下拉选择类型,多选一类型,不同于Many2one类型,Selection类型在数据库中对应的类型是int4或varchar类型。

除了通用的属性,另外接收2个参数:

  • selection: 可选的范围值,值和名称组成的元组列表。
  • validate: 默认True,是否写入时校验。

Selection包含如下的属性或方法:

  • get_values: 返回可选的值列表。

从14.0版本开始Selection开始支持ondelete属性,并且如果Selection是通过继承方式拓展了选项,那么ondelete属性是必须要指定的。

例如,由笔者开发的百度地图视图模块在升级到14.0版本的过程中,就碰到了这个问题,因为百度地图视图模块新增了一个视图类型,因此,要指定ondelete方法来指明模块在卸载时,应该如何处理这个新增的类型数据。

type = fields.Selection(
        selection_add=[("bmap", "百度地图")], ondelete={'bmap': "set default"}, default="form")

可选的处理选项有:

  • set null:默认选项,将字段设置为False
  • cascade:设置了这个选项的记录将被一同删除
  • set default:将所有设置的了这个值的记录还原为默认值
  • :定制化处理方式,第一个参数为使用了此值的所有记录。

大多数情况下,我们在开发过程中只需要关注Selection字段的key部分, 极少数的情况下可能会有这样的需求, 想要获取到Selection字段的描述部分的值. 这种时候,我们就可以使用下面的方法获取:

selection_field = fields.Selection([('a','A'),('b','B')])
...

def get_selection_value(self): 
  description = dict(self._fields[selection_field].selection).get(self.selection_field)
  return description

Monetary

odoo中对于货币类型的数值单独做了一个字段用来处理,这个字段就是Monetary。Monetary的基本使用方法同Float类型一致,不同的是Monetary的值会更精确,同时Monetary的值还依赖于当前计算环境的币种。

默认情况下要使用Monetary字段,需要在当前模型中同时新增一个currency_id的Many2one的字段,该字段表明本模型使用的货币类型(res.currency)。

例如:

currency_id = fields.Monetary("res.currency","货币")
amount = fields.Monetary("小计")

在视图中,如果需要带上货币符号,我们可以使用monetary小部件:

<field name="amount_total" widget="monetary" options="{'currency_field': 'currency_id'}"/>

如果不想使用默认的currency_id字段,可以在options中传入指定的货币类型字段名。

Reference

引用类型(继承自Selection),对应数据库类型varchar,Reference字段不同于Many2*类型的地方在于Many2*类型的字段的comodel是固定的,而Reference可以提供一种动态的选择。

比如,我们给模型book添加了一个ref字段,类型为Reference,关联两种类型,一个出版商,一个作者,那么ref字段就可以供用户在使用的时候自行选择绑定的记录:

Many2one

多对一类型,对应于数据库中的类型是int4,相当于数据库主表中的外键。可选的参数如下:

  • comodel_name: 被关联的对象
  • domain: 过滤条件
  • context: 上下文
  • ondelete: 删除时的选项,可选set null(本字段设置null),restrict(严格控制,只有先删除本字段才允许删除)和cascade(级联删除本字段关联的所有记录)。
  • auto_join: 当字段被搜索时是否自动聚合,默认为False
  • delegate: 当设置为True时,关联对象的所有字段将在本字段变得可用。

One2many

一对多类型,返回值是一个关联对象的集合。接收的参数列表如下:

  • comodel_name: 关联对象名称
  • inverse_name: 在Many2one对象中的字段名 默认为None
  • domain: 过滤条件
  • context: 上下文
  • auto_join: 当字段被搜索时是否自动聚合,默认为False
  • limit: 读取的条数限制
  • copy: 是否允许拷贝(默认False)

对于One2many和Many2many对象,有几种特殊的操作命令, 具体如下列表:

命令符解释举例命令结构*
CREATE根据values里的值创建一条新记录Commmand.create({'name':'张三'})(0,0,{values})
UPDATE根据values的值更新id对应的记录Command.update(1,{'name':'王心怡'})(1,ID,{values})
DELETE删除id=ID的这条记录Command.delete(1)(2,ID)
UNLINK切断主从关系,但不删除该数据Command.unlink(1)(3,ID)
LINK为id=ID的数据添加关联关系,3的反向操作Command.link(1)(4,ID)
CLEAR删除所有的主从关系,等价于循环调用记录集中的UNLINK方法Command.clear()(5,)
SET用IDS中的记录替换原来的记录, 等价于先使用CLEAR命令再循环调用LINK命令Command.set([1,2,3])(6,0,[IDS])

*15.0版本之前的命令是需要自己进行拼接的, 具体地讲,每个命令字都对应一个由元组组成的数据结构, 很显然, 开发者需要记住命令字中的1-6所代表的含义,以及他们的参数信息. 而15.0版本开始, odoo这些命令用更加容易的方式替代了.

Many2many

多对多关系类型的字段,Many2many的命令字与One2many相同,与One2many类型不同的是, One2many要对关联对象有一个回溯本身对象的inverse_name字段,而Many2many字段并无此限制。

Many2many字段的主要属性参数如下:

  • comodel_name:关联对象名
  • relation:关系表名
  • column1:本对象的关联字段名
  • column2:关联对象的关联字段名
  • domain: 过滤条件
  • context: 上下文
  • limit: 读取条数限制

与One2many类似,但不同的是参数中多了一个relation,用来存储多对多关系的表名,需要注意的是,relation,column1和column2可以不提供,odoo会根据model名称自动生成,但是需要保证column1和column2是不同的值。

举例来说,我们在第二章中创建的图书模型, 它的作者字段仅仅是一个字符字段,并没有更多的信息可以提供. 现实世界中,一本书可能有多个作者,一个作者也会写多本书,所以它们之间更合理的关系应该是多对多。现在我们将其更改为Many2many类型的字段,并关联一个新创建的对象,book_store.author。·

class book_store_author(models.Model):

  _name = "book_store.author"
  _description = "图书作者"

  name = fields.Char("姓名")

这里我们只简单地定义一个姓名字段. 然后我们将book_store.book对象的作者字段变更为Many2many:

author = fields.Many2many("book.author", string="作者")

为了展示Command命令的效果, 我们这里添加4个方法:

def button_create(self):
    """创建作者方法"""
    self.authors = [Command.create({
        "name": "瑶瑶"
    })]

def button_update(self):
    """更新作者方法"""
    self.authors = [Command.update(author.id, {
        "name": f"❤{author.name}"
    }) for author in self.authors]

def button_delete(self):
    """删除一个作者"""
    if not self.authors:
        raise AccessDenied("没有更多作者了")
    author_id = self.authors[0]
    self.authors = [Command.delete(author_id.id)]

def button_clear(self):
    """"删除所有作者"""
    self.authors = [Command.clear()]

分别点击这4个按钮可以查看相应的效果。

对于One2many的字段类型,存在一个反向关联的字段,而对于Many2many类型的字段,如何建立它的反向关联字段呢?答案参考附录。

Id

integer类型,对应数据库中的int4,针对与字段Id而专门设计的类型。Id字段是存储在数据库中的只读类型,不能被更新。

当我们使用self.id获取记录的id值时,实际上是读取了record本身的_ids的值,如果_ids的值为空,那么返回False。如果_ids的长度大于1,则触发类型错误(TypeError)。

虽然我们知道获取还可以通过self.ids获取记录集的id列表,但是他们却不是用的同样的原理,关于ids的更多知识参见模型一章。

计算值

上面所提到的字段类型都可以传入一个compute参数使之成为一个计算值。


def _get_name(self):
    self.name = "韩菱纱"

name = fields.Char(compute="_get_name",string="名称")

compute接一个计算方法,在方法内部设置该字段的值。计算值默认是不存储在数据库内的,如果要让他存储在数据库中,则需要搭配store=True参数进行使用。 另外,默认情况下,非存储值是不可以被搜索的。如果想要搜索计算字段,则需要使用search属性, 具体请参考新API一章.

总结

至此,我们学习了odoo的基本的字段类型,下一章我们将开始了解基本的视图结构,了解odoo视图的基本结构。

警告,添加自定义字段时,不要使用x这种奇怪的命名方式,x开头的字段会被系统识别为由界面上添加的字段,从而禁止你再次修改改字段。请记住一点,不要随便使用开发者模式添加或删除自己不知道后果的数据,否则,你的数据库可能很快就因为你不知道的原因而崩溃。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值