odoo

Packer.Odoo.10---Chapter 3

2017-09-27  本文已影响200人  F4A3

继承-扩展原有的应用

Odoo中,有一个非常重要的特色,不用直接修改底层对象就能为我们的模块添加新的功能。这个特色就是Odoo中的继承(inheritance)机制.继承能够在不同的层面上(models,views,business logic)来进行对原有模块的修改。

为我们的To-Do app增加分享功能

我们的To-Do应用允许用户管理他们自己的to-do 任务,我们接下来需要创建一个新
的模块来扩展前一章的To-Do应用,运用继承机制来添加分享任务和讨论功能。
我们的工作计划如下:

{
    'name': 'Multiuser To-Do',
    'description': 'Extend the To-Do app to multiuser.',
    'author': 'Daniel Reis',
    'depends': ['todo_app'],
}

注意到我们添加了对原先的'todo_app'模块的依赖'depends':['todo_app'].这对我们的继承机制是十分重要的.当我们添加了'depend'后,每次更新我们的'todo_user'模块,它对应的依赖'todo_app'会自动更新.


扩展我们的模型(models)

python的classes能够定义新的models.我们对models扩展需要使用Odoo的继承机制来编写classes.

我们来扩展我们的todo.task模型, 添加2个新的字段:1.task的负责人 2.task的截止日期
创建'/todo_user/models'文件夹,其中创建'todo_task.py'文件,添加以下代码

from odoo import models,fields,api
class TodoTask(models.Model):
    _inherit = 'todo.task'
    user_id = fields.Many2one('res.users', string='Responsible')
    date_deadline = fields.Date('Deadline')
修改已经存在的字段

就像我们看到的,添加一个新的字段到我们已经存在的模型是相当直接的.从Odoo 8开始,修改模块中已经存在的字段的属性也是可以实现的,做法很简单,添加一个与存在的字段名称相同的字段,然后只修改字段的属性的值就可以了.举例来说,我们添加下列字段到我们的'todo_task.py'中:
name = fields.Char(help="What needs to be done?")

修改模型的方法

继承机制对业务逻辑层面同样适用,添加新的方法跟添加字段一样简单:直接在class类中添加即可.
跟python的继承类似,当我们适用Odoo的继承机制时,我们在新的继承类中定义与父类相同名字的函数同样可以实现重写.而且在继承类中使用super()
函数来调用父类的方法.
注意点:重写方法时,尽量不要修改传入方法的参数列表,如果实在需要,可以使用关键字参数来实现.

    @api.multi
    def do_clear_done(self):
        domain = [('is_done', '=', True),
                  '|', ('user_id', '=', self.env.uid),
                  ('user_id', '=', False)]
        dones = self.search(domain)
        dones.write({'active': False})
        return True
from odoo.exceptions import ValidationError
    @api.multi
    def do_toggle_done(self):
        for r in self:
            if r.user_id != self.env.user:
                raise ValidationError(
                    'Only the responsible can do this!'
                )
        return super(TodoTask, self).do_toggle_done()
扩展views视图

表单(forms),列表(list),搜索(search)视图都是被'arch'所定义的XML结构.为了扩展视图,我们需要修改这些xml,这就意味着要定位xml元素然后对它们进行修改.
一个继承的视图代码:

      <record id="view_form_todo_task_inherited" model="ir.ui.view">
          <field name="name">Todo Task form Inherited</field>
          <field name="model">todo.task</field>
          <field name="inherit_id"
                 ref="todo_app.view_form_todo_task"/>
          <field name="arch" type="xml">
       <! -- ..match and extend elements here! ..-->
        </field>
        </record>
<xpath expr="//field[@name]='is_done'" position="before"/>
<field name="date_deadline"/>
</xpath>
<field name="is_done" position="before">
     <field name="date_deadline"/>
</field>
<field name="active" position="attributes">
  <attribute name='invisible'>1</attribute>
</field>

这段代码表示把'acitve'这个字段隐藏起来

扩展form视图

编写views/todo_task.xml,
添加的完整的form视图代码如下:

        <record id="view_form_todo_task_inherited" model="ir.ui.view">
            <field name="name">Todo Task form Inherited</field>
            <field name="model">todo.task</field>
            <field name="inherit_id"
                 ref="todo_app.view_form_todo_task"/>
            <field name="arch" type="xml">
                <xpath expr="//field[@name='is_done']" position="after">
                    <field name="date_deadline"></field>
                </xpath>
                <xpath expr="//field[@name='name']" position="after">
                    <field name="user_id"></field>
                </xpath>
                <xpath expr="//field[@name='active']" position="attributes">
                    <attribute name="invisible">1</attribute>
                </xpath>
            </field>
        </record>

最后在__manifest__.py中添加todo_task.xml到data属性
'data':['views/todo_task.xml'],

扩展tree跟search视图

与form视图一样,运用inherit_id 这个field来实现继承,在tree视图中,我们添加user_id字段。

 <record id="view_tree_todo_task_inherited" model="ir.ui.view">
    <field name="name">Todo Task tree Inherited</field>
    <field name="model">todo.task</field>
    <field name="inherit_id" ref="todo_app.view_tree_todo_task"/>
    <field name="arch" type="xml">
    <field name="name" position="after">
    <field name="user_id"/>
                </field>
            </field>
        </record>

在search视图我们添加2个新的过滤条件:1.用户自己的任务。2. 那些没有负责人的任务

        <record id="view_filter_todo_task_inherited" model="ir.ui.view">
            <field name="name">Todo Task filter Inherited</field>
            <field name="model">todo.task</field>
            <field name="inherit_id" ref="todo_app.view_filter_todo_task"/>
            <field name="arch" type="xml">
                <field name="name" position="after">
                    <field name="user_id"/>
                    <filter name="filter_my_tasks" string="My Tasks"
                            domain="[('user_id','in',[uid,False])]"/>
                    <filter name="filter_not_assigned" string="Not Assigned"
                            domain="[('user_id','=',False)]"/>
                </field>
            </field>
        </record>

模型继承机制的更多介绍

我们下面举例子来进行说明

使用prototype inheritance来复制功能

我们在前面的扩展模型只使用了_inherite属性,我们定义了一个模型去继承'todo.tasl'模型,添加了一些功能,但我们没有使用_name.所以继承模块还是使用todo.task的数据库表结构.

from odoo import models
class TodoTask(models.Model):
    _name = 'todo.task'
    _inherit = 'mail.thread'

这个例子很好理解,我们通过_inherit把'mail.thread'这个模块的所有信息复制到了'todo.task'模型的数据库表结构中.
复制意味着父模块中的所有方法跟字段都被添加到子模块中.我们的例子里就是把'mail.thread'定义的方法跟字段都添加到了'todo.task'.但是'mail.thread'跟'todo.task'都拥有自己独立的数据库表结构,它们之间没有任何联系.只是共享了fields的定义而已.

通过委托继承(delegation inheritance)植入模型

委托不是那么常用,但是它能提供很多方便的继承解决方法。它使用_inherites属性通过字典映射继承模块与字段之间的关系.一个很好的例子就是我们的标准用户模型,'res.users',它植入了一个Partner模型.

from odoo import models, fields
class User(models.Model):
    _name = 'res.users'
    _inherits = {'res.partner': 'partner_id'}
    partner_id = fields.Many2one('res.partner')
添加社交网络功能

社交网络模块(mail)在form视图的底部提供了消息板跟关注者功能。我们经常需要添加这些消息传递逻辑到我们的模块,下面就开始操作

'depends':['todo_app','mail']
_name = 'todo.task'
_inherit = ['todo.task','mail.thread']
                <sheet position="after">
                    <div class="oe_chatter">
                        <field name="message_follower_ids"
                               widget="mail_followers"/>
                        <field name="message_ids" widget="mail_thread"/>
                    </div>
                </sheet>
修改数据记录

不同于views中的xml,普通的数据记录没有XML arch结构,无法被Xpath定位到,但我们任然可以通过<record id='x' model='y'>来插入或者修改普通数据记录。(x不存在就是插入,存在即为修改)

修改菜单,动作记录。
        <!--modify menu item-->
    <record id="todo_app.menu_todo_task" model="ir.ui.menu">
        <field name="name">My To-Do</field>
    </record>

        <record model="ir.actions.act_window"
                id="todo_app.action_todo_task">
            <field name="context">
                {'search_default_filter_my_tasks':True}
            </field>
        </record>
修改安全记录规则

前一个章节中,我们的todo_app的记录规则在于创立task的用户才能看到对应的task,现在由于社交功能的加入,只要是task的关注者,都能看到该task.
我们创建/todo_user/security/todo_access_rules.xml文件,添加以下代码。

<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
    <data noupdate="1">
        <record id="todo_app.todo_task_per_user_rule"
                model="ir.rule">
            <field name="name">ToDo Tasks for owner and followers</field>
            <field name="model_id" ref="model_todo_task"/>
            <field name="groups" eval="[(4, ref('base.group_user'))]"/>
            <field name="domain_force">
                ['|',('user_id','in',[user.id,False]),
                    ('message_follower_ids','in',[user.partner_id.id])]
            </field>
        </record>
    </data>
</odoo>
上一篇 下一篇

猜你喜欢

热点阅读