提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
今天介绍的是odoo中一个常用的mixin功能扩展。在单据Form视图中,我们经常在视图的底部看到会有一个类似日志输出的内容,如下图所示:
这个内容主要包括有一个关注者信息、单据消息记录、单据附件信息,还有一个活动计划的信息,是由另一个mixin扩展来实现的,我放到后面再来讲。
odoo把这些功能封装到了一个mixin,这样所有需要此功能的数据模型,都可以继承此mixin使用。
注意: 这个mixin是在mail模块中,所以__manifest__文件需要depends这个模块
一、mail.thread
这两部分功能分别对应数据库的两个表,mail.followers存放关注者的数据。mail.message存放单据对应的消息记录数据。odoo框架将这两者结合在了mail.thread抽象模型里,并形成一个可继承的,整体使用的mixin。
如图所示,mail.thread继承的是models.AbstractModel抽象模型,并且对应的字段属性都是computer类型且未设置store=True,不会生成实体的数据表字段。
实际业务模型中要使用这个功能的话,一般需要两个步骤。
- 定义的数据模型继承mail.thread。
- 定义的数据视图上增加对应的div元素
二、使用示例
1.继承模型
代码如下(示例):
class Department(models.Model):
_name = "hr.department"
_description = "Department"
_inherit = ['mail.thread']
2.视图引用
代码如下(示例):
<form>
<sheet>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="message_ids"/>
</div>
</form>
在view中定义了两个字段,一个是关注者列表,另一个是消息列表。
定义的div中元素中,class="oe_chatter"是固定的。在mail模块中,JS文件(form_renderer.js)重写了渲染逻辑,如下所示:
_renderNode(node) {
if (node.tag === 'div' && node.attrs.class === 'oe_chatter') {
if (this._isFromFormViewDialog) {
return $('<div/>');
}
return this._makeChatterContainerTarget();
}
return this._super(...arguments);
},
从_renderNode方法中可以知道。如果元素是div,class为oe_chatter,并且不是弹框形式时。会执行_makeChatterContainerTarget方法进行渲染。
注意:如果是弹框形式展示的form视图。odoo一般会隐藏关注者和消息列表的。就是通过_isFromFormViewDialog属性控制的
另一个主要实现的方法是如下重载方法:
async __renderView() {
await this._super(...arguments);
if (this._hasChatter()) {
if (!this._chatterContainerComponent) {
this._makeChatterContainerComponent();
} else {
await this._updateChatterContainerComponent();
}
await this._mountChatterContainerComponent();
}
}
这里判断了form想要显示消息列表时需要调用的方法、qweb模板等。14版本的渲染模板采用新的owl方式,大家有空可以学习一下。
三、创建消息记录
上面讲了怎么把mixin加入自己的业务中,但是加入之后,需要怎么忘这个消息列中手动或自动创建消息记录呢。
1.tracking 属性
在数据模型定义的字段中,添加tracking属性,如:
user_id = fields.Many2one('res.users', string='Salesperson', index=True, tracking=True, default=lambda self: self.env.user)
当tracking属性值为True或数字时,系统会在这个字段内容有变化时,将变化前后的值写入消息记录日志。而当tracking的属性值为数字时,会影响其在日志中的排序。
2.message_post
可以在执行的代码中,通过message_post方法来提交一个自定义的消息记录。
这个mixin还提供了很多接口方法。不只是有能处理日志类消息的方法,还有处理邮件、附件等类型的方法,这里就不在一一说明,大家可以从mail.thread的模型定义中查看具体使用方法与实现逻辑