odoo 开发入门教程系列 |
您所在的位置:网站首页 › odoopython教程 › odoo 开发入门教程系列 |
继承(Inheritance) Odoo的一个强大方面是它的模块化。模块专用于业务需求,但模块也可以相互交互。这对于扩展现有模块的功能非常有用。例如,在我们的房地产场景中,我们希望在常规用户视图中直接显示销售人员的财产列表。 在介绍特定的Odoo模块继承之前,让我们看看如何更改标准CRUD(创建、检索,更新或删除)方法的行为 Python继承(Python Inheritance)目标: 不能删除状态不为New、Canceled的房产预期效果动画地址:https://www.odoo.com/documentation/14.0/zh_CN/_images/unlink.gif在我们的房地产模块中,我们从不需要开发任何特定的东西来执行标准的CRUD操作。Odoo框架提供了实现这些操作的必要工具。事实上,多亏经典的Python继承,我们的模型中已经包含了这样的操作: from odoo import fields, models class TestModel(models.Model): _name = "test.model" _description = "Test Model" ...我们的 TestModel 类继承与Model,该Model类提供了 create(), read(), write() 和unlink()方法。 这些方法(和其它在Model中定义的任何方法)可被扩展以添加指定业务逻辑: from odoo import fields, models class TestModel(models.Model): _name = "test.model" _description = "Test Model" ... @api.model def create(self, vals): # Do some business logic, modify vals... ... # Then call super to execute the parent method return super().create(vals)model()装饰器对于create() 方法来说是必需的,因为结果集self的内容和创建(creation)的上下文无关,但该装饰器对于其它CRUD方法来说不是必需的。 Python 3中, super() 等价于 super(TestModel, self)。当你需要使用一条被修改后的结果集调用父方法时,可能需要使用后者。 危险提示 总是调用 super()以避免中断流非常重要。只有少数非常特殊的情况才无需调用它。总是返回和父方法一致的数据。例如父方法返回一个dict(),你重写父方法时也要返回一个dict()练习--添加业务逻辑到CRUD方法 如果房产记录状态不是New,Canceled,则不让删除提示:重写unlink() ,并记住self可以是一个包含多条记录的结果集。 创建报价时,设置房产状态为‘Offer Received’,如果用户试图以低于已存在报价的金额创建报价时抛出错误。提示: 可在vals中获取property_id 字段,但是它是一个int型。要实例化一个estate.property 对象,请使用self.env[model_name].browse(value) (示例) @api.model def create(self, vals): self.env['gamification.badge'].browse(vals['badge_id']).check_granting() return super(BadgeUser, self).create(vals)修改odoo14\custom\estate\views\estate_property_views.xml 去掉estate_property_view_tree 中元素的editable="top"属性(说明:为了方便执行报价创建操作) 修改odoo14\custom\estate\models\estate_property.py @api.constrains('selling_price', 'expected_price') def _check_selling_price(self): # if record.selling_price < self.expected_price * 0.9: # raise ValidationError("selling price can`t not lower then 90 percent of expected price") pass说明:为了方便实践操作,暂且不做售价校验 最末尾新增以下代码 def unlink(self): for record in self: if record.state not in ['New', 'Canceled']: raise UserError('can`t delete property which status is New or Canceled') return super().unlink()修改odoo14\custom\estate\models\estate_property_offer.py,导入UserError from odoo.exceptions import UserError最末尾添加一下代码 @api.model def create(self, vals): property = self.env['estate.property'].browse(vals['property_id']) if vals.get('price') < property.best_price: raise UserError('不能低于现有报价') property.state = 'Offer Received' return super().create(vals)重启服务,刷新浏览器验证 删除非New、Canceled状态的房产,提示如下: 引用: 查看主题相关文档继承和扩展 我们希望在“Settings/Users & Companies/Users”表单视图中直接显示与销售人员关联的房产列表。为此,我们需要向res.users模型添加一个字段,并调整其视图以显示它。 Odoo提供了两种继承机制来以模块化的方式扩展现有模型。 第一继承机制允许模块通过以下方式修改在另一个模块中定义的模型的行为: 向模型添加字段覆盖模型中字段的定义给模型添加约束给模型添加方法重写模型中的现有方法第二种继承机制(委托)允许将模型的每个记录链接到父模型的记录,并提供对该父记录的字段的透明访问。 odoo中,第一种机制最常用。在我们的例子中,我们希望向现有模型添加一个字段,这意味着我们将使用第一种机制。例如: from odoo import fields, models class InheritedModel(models.Model): _inherit = "inherited.model" new_field = fields.Char(string="New Field")这里可以找到将两个字段添加到模型中的示例 class AccountMoveLine(models.Model): _inherit = 'account.move.line' vehicle_id = fields.Many2one('fleet.vehicle', string='Vehicle') need_vehicle = fields.Boolean(compute='_compute_need_vehicle', help="Technical field to decide whether the vehicle_id field is editable") def _compute_need_vehicle(self): self.need_vehicle = False按照惯例,每个继承的模型都在其自己的Python文件中定义。在我们的示例中为“models/inherited_model.py”。 练习--添加字段到用户模型添加一下字段到res.users:Field Type property_ids One2many inverse of salesman_id to estate.property 添加一个domain到该字段,这样以便仅显示可获取房产。新增odoo14\custom\estate\models\estate_res_user.py #!/usr/bin/env python # -*- coding:utf-8 -*- from odoo import models, fields class EstateResUser(models.Model): _inherit = 'res.users' property_ids = fields.One2many('estate.property', 'salesman_id', domain="[('salesman_id', '=', active_id)]")修改odoo14\custom\estate\models\__init__.py #!/usr/bin/env python # -*- coding:utf-8 -*- from . import estate_property_type from . import estate_property_tag from . import estate_property_offer from . import estate_property from . import estate_res_user # 本次新增视图继承(View Inheritance)参考: 主题关联文档可查看Inheritance. 目标: 在用户表单视图中显示与销售人员关联的avaliable房产列表其用户表单视图 Odoo提供了视图继承,其中子“扩展”视图应用于根视图之上,而不是就地修改现有视图(通过重写它们)。这些扩展既可以添加内容,也可以从父视图中删除内容。 扩展视图使用inherit_id字段引用其父视图。它的arch字段包含多个xpath元素,用于选择和更改父视图的内容,而不是单个视图: inherited.model.form.inherit.test inherited.model expr一个用于选择父视图中单个元素的XPath表达式。如果不匹配任何元素或者匹配多个元素,则抛出错误position应用于匹配元素的操作:inside将xpath的主体附加到匹配元素的末尾(个人理解,添加为匹配元素的子元素)replace将匹配元素替换为xpath的主体,将新主体中出现的任何$0节点替换为原始元素before在匹配元素之前插入xpath的主体作为同级元素after在匹配的元素之后插入xpaths的主体,作为同级元素attributes使用xpath主体中的特定属性元素更改匹配元素的属性当匹配单个元素时,可以直接在要查找的元素上设置position属性。以下两种继承都有相同的结果 在这里可以找到视图继承扩展的示例 account.move.form account.move 练习--添加字段到用户视图添加property_ids字段到 base.view_users_form 中新建的notebook页 提示: 可以在 这里找到继承用户视图的示例。 res.users.view.form.inherit.gamification res.users新增odoo14\custom\estate\views\estate_res_users_views.xml estate.res.users.view.form res.users修改odoo14\custom\estate\__manifest__.py #!/usr/bin/env python # -*- coding:utf-8 -*- { 'name': 'estate', 'depends': ['base'], 'data':['security/ir.model.access.csv', 'views/estate_property_views.xml', 'views/estate_property_type_views.xml', 'views/estate_property_tag_views.xml', 'views/estate_property_offer_views.xml', 'views/estate_menus.xml', 'views/estate_res_users_views.xml' # 本次新增 ] }重启服务,验证效果 作者:授客 全国软件测试QQ交流群:7156436
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |