### 视图继承 代替修改现有的视图(通过重写它们),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> ~~~