### 视图继承
代替修改现有的视图(通过重写它们),Odoo提供观的传承在孩子们“延伸”的观点应用在顶部的根视图,并可以添加或删除从父内容。
继承视图参考使用` inherit_id `字段它的父,而不是一个单一的视图`arch`字段是由任意数量的` XPath `要素选择和改变他们的父视图的内容:
~~~ xml
<!-- improved idea categories list -->
<record id="idea_category_list2" model="ir.ui.view">
<field name="name">id.category.list2</field>
<field name="model">idea.category</field>
<field name="inherit_id" ref="id_category_list"/>
<field name="arch" type="xml">
<!-- find field description and add the field
idea_ids after it -->
<xpath expr="//field[@name='description']" position="after">
<field name="idea_ids" string="Number of ideas"/>
</xpath>
</field>
</record>
~~~
`expr`
一个 [XPath](http://w3.org/TR/xpath) 表达式选择父视图中的一个元素。如果匹配没有元素或多个元素,则引发错误
`position`
操作来应用于匹配元素:
`inside`
追加` XPath `的身体在匹配元素的结束
`replace`
由` XPath `身体替换匹配的元素
`before`
插入` XPath `的身体在匹配元素的兄弟姐妹
`after`
插入` XPath `的身体作为匹配的元素后,兄弟姐妹
`attributes`
改变属性的匹配元素中使用特殊的`属性`元素在` XPath `的身体
Tip
在匹配单个元素时,可以直接设置“位置”属性,以找到该元素。既继承下面会给出相同的结果。
~~~ xml
<xpath expr="//field[@name='description']" position="after">
<field name="idea_ids" />
</xpath>
<field name="description" position="after">
<field name="idea_ids" />
</field>
~~~
练习
改变现有内容
* 使用模型的继承,修改现有的*伙伴*模型添加一个`教练`布尔字段,和many2many场对应的会话伙伴关系
* 使用视图继承,在合作伙伴表单视图中显示该字段
Note
这是机会介绍的开发模式,以检查的观点,找到它的外部标识和地方,把新的领域。
1. 创建一个文件 `openacademy/partner.py` 然后在 `__init__.py` 中引入它
2. 创建一个文件 `openacademy/views/partner.xml` 然后在 `__openerp__.py` 中引入它
*openacademy/__init__.py*
~~~ python
# -*- coding: utf-8 -*-
from . import controllers
from . import models
from . import partner
~~~
*openacademy/__openerp__.py*
~~~ python
# 'security/ir.model.access.csv',
'templates.xml',
'views/openacademy.xml',
'views/partner.xml',
],
# only loaded in demonstration mode
'demo': [
~~~
*openacademy/partner.py*
~~~ python
# -*- coding: utf-8 -*-
from openerp import fields, models
class Partner(models.Model):
_inherit = 'res.partner'
# Add a new column to the res.partner model, by default partners are not
# instructors
instructor = fields.Boolean("Instructor", default=False)
session_ids = fields.Many2many('openacademy.session',
string="Attended Sessions", readonly=True)
~~~
*openacademy/views/partner.xml*
~~~ xml
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<!-- Add instructor field to existing view -->
<record model="ir.ui.view" id="partner_instructor_form_view">
<field name="name">partner.instructor</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<notebook position="inside">
<page string="Sessions">
<group>
<field name="instructor"/>
<field name="session_ids"/>
</group>
</page>
</notebook>
</field>
</record>
<record model="ir.actions.act_window" id="contact_list_action">
<field name="name">Contacts</field>
<field name="res_model">res.partner</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="configuration_menu" name="Configuration"
parent="main_openacademy_menu"/>
<menuitem id="contact_menu" name="Contacts"
parent="configuration_menu"
action="contact_list_action"/>
</data>
</openerp>
~~~
#### 领域
在Odoo, [Domains](https://www.odoo.com/documentation/9.0/reference/orm.html#reference-orm-domains) 在记录上编码条件的值。域是用来选择模型记录集的一个子集的标准列表。每一个标准都是一个带着一个字段名、一个操作符和一个值的三元组。
例如,当使用在 *产品* 模型上,下面的域选择一个单位价格超过 *1000* 的所有 *服务* :
~~~ python
[('product_type', '=', 'service'), ('unit_price', '>', 1000)]
~~~
默认的标准是一个隐含的和。逻辑运算符`&`(与),`| `(或)和 `!`(非)可用于显式地结合标准。它们被用来在前缀位置(在它的参数之间插入操作符,而不是在它们之间)。例如,选择产品“服务 *或* 有一个单位的价格,这是 *非* 在1000和2000之间”:
~~~ python
['|',
('product_type', '=', 'service'),
'!', '&',
('unit_price', '>=', 1000),
('unit_price', '<', 2000)]
~~~
在试图在客户机接口中选择记录时,可以添加一个“域”参数,以限制该关系的有效记录。
练习
关系领域的字段
当选择一个教师为*会议*,只有导师(合作伙伴与教练的一个设置为“真实的”)应该是可见的。
*openacademy/models.py*
~~~ python
duration = fields.Float(digits=(6, 2), help="Duration in days")
seats = fields.Integer(string="Number of seats")
instructor_id = fields.Many2one('res.partner', string="Instructor",
domain=[('instructor', '=', True)])
course_id = fields.Many2one('openacademy.course',
ondelete='cascade', string="Course", required=True)
attendee_ids = fields.Many2many('res.partner', string="Attendees")
~~~
Note
被声明为一个文本列表的域被评估为服务器端,并且不能在右侧的动态值,一个域声明为一个字符串被评估的客户端,并允许在右侧的字段名称
练习
更复杂的领域
创建新的合作伙伴类别*教师/ 1级*和*教师/ 2级*。教师的一个会话可以是一个教师或教师(任何级别)。
1. 修改*会话*模型的域
2. 修改 `openacademy/view/partner.xml` 访问伙伴分类:
*openacademy/models.py*
~~~ python
seats = fields.Integer(string="Number of seats")
instructor_id = fields.Many2one('res.partner', string="Instructor",
domain=['|', ('instructor', '=', True),
('category_id.name', 'ilike', "Teacher")])
course_id = fields.Many2one('openacademy.course',
ondelete='cascade', string="Course", required=True)
attendee_ids = fields.Many2many('res.partner', string="Attendees")
~~~
*openacademy/views/partner.xml*
~~~ xml
<menuitem id="contact_menu" name="Contacts"
parent="configuration_menu"
action="contact_list_action"/>
<record model="ir.actions.act_window" id="contact_cat_list_action">
<field name="name">Contact Tags</field>
<field name="res_model">res.partner.category</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="contact_cat_menu" name="Contact Tags"
parent="configuration_menu"
action="contact_cat_list_action"/>
<record model="res.partner.category" id="teacher1">
<field name="name">Teacher / Level 1</field>
</record>
<record model="res.partner.category" id="teacher2">
<field name="name">Teacher / Level 2</field>
</record>
</data>
</openerp>
~~~