数据模型的设计:
区分实体模型、瞬态模型、抽象模型。
实体模型:数据需要持久化存储在数据库中。
瞬态模型:向导,临时数据,不需要持续化在数据库中的数据。
抽象模型:定义的底层模型、供其他实体模型继承的基础模型。
模型定义
模型名能清晰表达出该模型的含义或应用。
模型名连接符只能使用“.”符号,全部使用小写字母,尽量不使用缩写。
(3) 定义模型时必须声明_description。
(4) 合理使用 _order 属性,建议声明。
(5) 继承其它模块的模型时,要确保有直接过间接的依赖关系。
(6) 模型没有name字段时,声明_rec_name属性。
字段
保留字段
会自动在模型数据表中创建的字段,特殊需要时可以重写,但保持类型不变。
Datetime类型:create_date、write_date、__last_update
Integer类型:id、create_uid、write_uid
Char类型:display_name
注意事项:model的_log_access属性用来控制是否添加默认字段create_date、write_date、create_uid、write_uid,默认_log_access=True,等于False时则不添加默认字段。
特殊字段
(1) name:默认name为_rec_name(显示名称), 可以通过模型的 _rec_name属性指定显示的名称,没有name字段一定要写_rec_name。
(2) active:默认情况下搜索时会跳过active=False的数据,但可以通过在context参数中增加active_test=False来搜索所有数据。在action中使用:
{‘active_test’: False}
来支持点击菜单时查看包含active=False的所有数据。
(3) sequence:在可编辑(editable=top or bottom)的tree视图和form视图的列表中,支持上下拖动行记录数据,拖动后所有当前列表中的数据的sequence序列将重新排序。
(4) state:状态在字段states属性和view上都有特殊应用:
Python:
states={‘draft’:[(‘readonly’,False)], ‘confirm’:[(‘required’,False)]}
view中的应用(一般位于header标签内,statusbar_visible指定默认显示出来的value,statusbar_colors已经不再使用):
(5) parent_id:view_type为tree时根据parent_id建立树状关系,同时在domain中针对该字段使用child_of搜索条件,在所有后代节点的数据中查找。
(6) parent_left、parent_right:nested set mode(改进前序遍历树模型),模型的_parent_name属性默认为’parent_id’, 在模型包含parent_id字段、模型的属性_parent_store = True的情况下,创建数据和编辑parent_id字段时,自动维护该模型所有数据的parent_left、parent_right数值。
原理:在数据表中维护/建立的关系:parent left < child left 且 parent right > child right,用于直接查找数据节点之间的父子关系。
参见:http://my.oschina.net/amoswork/blog/280142
py字段定义中常见字段属性
(1) 字段名:小写字母,下划线命名法,含义清楚完整,尽量不使用缩写。string: 首字母大写。
(2) default:可以赋default值的字段,合理定义default值。
(3) index:为频繁read、不频繁write的字段建立索引:index=True(old_api: select)。
(4) auto_join: 为频繁链式读取的字段在建立joins:employee.user_id.login 则hr.employee模型中的user_id应auto_join=True。
(5) translate:value需要翻译的字段使用:translate=True,支持的字段类型:char、text、html,通常应用在配置数据、模板数据中,而非业务数据。
(6) ondelete:many2one字段谨慎使用 ondelete=‘cascade’ .
(7) relation、column1、column2:many2many字段,在两边模型都声明关联字段时,需要显式指定关联表及关联字段名称。
(8) store:是否将字段值存储在数据表中,常规字段默认store=True,store=False时,不会在数据表中创建该列。
在声明compute、related属性时,api.depends(fields),fields定义recompute 的条件
(9) compute:依赖store属性。
store=False时:该字段值根据compute指定的function动态计算(on-the-fly)
store=True时:创建该记录时,自动计算一次,存储在数据表中。编辑当前记录时,也会重新计算。
(10) related:已默认为readonly=True,在历史业务单据中,一般需要保留当时值的情况下,需要加store=True;对于特殊场景需要store=True且保持更新的情况下,添加update=True属性。
不允许related='field1.field2’中的field2是一个store=False的字段。
(11) inverse:类似于old api中的fuct_inv,同compute一起应用,给字段/记录赋值。
(12) search:搜索前处理/扩展domain条件,应用于关系型字段,返回值时domain。效果等同于name_search方法,但是参数不同。
(13) compute_sudo:compute_sudo=True表示使用SUPERUSER_ID执行compute方法。
(14) related_sudo:related _sudo=True表示使用SUPERUSER_ID计算related值。
(15) company_dependent:old api中的property字段。
(16) digits:精度控制元组,(total, decimal),应用于float字段。
(17) size:char类型字段的字符长度。
(18) required:是否必填
(19) readonly:是否只读
(20) states:控制某些state条件下字段的readonly、required、invisible属性,如:states={‘draft’:[(‘readonly’,False)], ‘confirm’:[(‘required’,False)]}
(21) help:提示信息(Tooltip)
(22) groups:逗号分隔的用户组(完整的xml_id)
(23) copy:copy=False时,复制record数据时不包含该字段值。
(24) domain:过滤条件,应用于关系型字段,value可以是一个函数来生成domain。
(25) context:context传递变量,应用于关系型字段。
(26) limit:one2many、many2many默认的limit数量(80)。
view中常见字段属性
(1) string
(2) domain
(3) invisible
(4) required
(5) readonly
(6) password
(7) groups
(8) context
(9) states:
<footer states="choose">
<button name="act_getfile" string="Export" type="object" class="btn-primary"/>
<button special="cancel" string="Cancel" type="object" class="btn-default"/>
</footer>
<footer states="get">
<button special="cancel" string="Close" type="object" class="btn-primary"/>
</footer>
(10) attrs:attributes
(11) ref:常用在data数据中指定xml_id
(12) eval:
(13) on_change:
(14) sum:该列是否在视图合计,sum=字符串名称。
(15) widget:url, float_time, percent, color, no_sep, short_time…
(16) width、img_width:
(17) height、img_height
(18) filename:二进制字段的显示名称。
(19) options:no_create、no_open、limit等
(20) placeholder:
字段应用
(1) 新增字段显示定义:分析字段是否可编辑、可搜索,在不同条件下的不同属性,以及出现在哪些视图中。
(2) 新增字段depends情况,store=True时related字段update属性。
Method
(1)方法的定义简洁、优美。一般业务逻辑代码不超过40行,不过度使用行内换行。
(2)合理使用装饰器,使用装饰器时,明确该方法的self是one record 还是multi record,或者只是模型的普通方法。
(3)search新API返回数据对象集合,old api返回id列表。
search_read方法返回值是字典组成的列表。
(4)确保write方法写入的目标对象是ids,而不是id。
(5)重载/重写已有方法,正确return返回值。
@api.model
def create(self, vals):
record_id = super(ImportFields, self).create(vals)
# 业务逻辑代码
return record_id
(6)每个方法必须要有三引号多行注释。
@api.model
def execute_model_func(self, model, func):
"""
执行model的相关function
:param model: 模型
:param func: 方法名
:return: 方法执行后的返回值
"""
(7)使用logging模块记录后台行为日志,杜绝在项目代码中使用print的不良习惯。
import logging
_logger = logging.getLogger(name)
…
_logger.warning(‘Validate Error!’)
(7)Controllers
用户读写数据的接口中定义auth=”user”.
接口的业务逻辑定义在模型的方法中。
升级导致的数据清理
(1) 删除模型
需要通过sql脚本清理对应数据:数据表,ir.model模型数据,ir.model.data模型数据。
(2) 删除字段
表字段,ir.model.fields,ir.model.data
(3) 删除约束
删除表约束,ir.model.constraints