### 視圖繼承
代替修改現有的視圖(通過重寫它們),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>
~~~