python - 在 OpenERP 中如何将继承对象视为子类?

标签 python odoo

这个问题可能比最初看起来更复杂。

假设我有一个父类 Animal(我们在 OpenERP 中将其命名为 animal.base)。我还有子类 Lion (animal.lion) 和 Elephant (animal.elephant)。我需要能够创建一个具有可以引用 Animal 的任何子类的 Many2one 字段的 View 。这似乎可以通过执行以下操作来实现:

class animal_lion(osv.osv):
    _name = 'animal.lion'
    _inherits = {'animal.base': 'base_id'}

    _columns = {
         ...
         'base_id': fields.many2one('animal.base', "Base ID")
    }

    def roar(self, cr, uid, context=None):
        print "rarrrrr"

现在,当我们创建 animal.lion 的实例时,我们可以看到它在引用 animal.base 的 View 中可见。 (简单的 inherit = 'animal.base' 不会这样做,FWIW。)

但是,现在假设我们需要使用这种动物的方法。由于 Many2one 仅引用 animal.base,因此我们不知道用户在 View 中选择了哪种动物。即使我们碰巧知道只有狮子会被选中,我们也不能调用 roar 因为 animal.base 对象只会让我们调用定义在本身。我们可以尝试通过命名方法 emit_sound 并尝试重写 Lion 类中的方法来绕过它。这至少会运行(除了 _inherits 之外添加一个 _inherit 后),但它不会产生正确的 Lion 特定输出。需要的是某种方法来确定在基类 x 上的 Many2one 中选择的特定实例的动态类型,其中多个子类在同一类 上指定 _inherits >x。想象一个虚构的方法 get_subtype()。然后我们可以在 View 的按钮处理程序中执行以下操作:

def perform(self, cr, uid, ids, context=None):
    this = self.browse(cr, uid, ids[0], context)
    subtype_name = this.my_many2one.get_subtype()
    subtype = self.pool.get(subtype_name)
    # will produce a roar if user picked a lion, else a meep
    subtype.emit_sound(cr, uid, context)

或者,是否有其他架构可以用来完成相同的任务? (是的,我设计了这个示例,但它应该说明真正的问题。) [也许在每个子类型实例的字段中对子类型名称进行编码? ]

我仅限于 OpenERP v5,但有兴趣知道任何版本的答案。

最佳答案

这里的关键是您希望您的 base.animal 作为所有动物的公共(public)索引单独存在于数据库中,因此这会使您的数据模型变得非常复杂,并迫使您使用记录-级别继承(通过_inherits)。

为了解析动物的子类型,您应该在 animal.base 中添加显式的 type 列,并始终正确设置它,以便您可以推断子类型记录.

# This static list could also be replaced by a function
ANIMALS = [
    ('lion', 'Lion'),
    ('elephant', 'Elephant'),
]
class animal_base(osv.osv):
    _name = 'animal.base'
    _columns = {
         ...
         'type': fields.selection(ANIMALS, 'Type'), 
    }

您的 base.animals 将独立存在于数据库中,并且可以拥有自己的 View ,因为您使用的是记录级继承。 子类型(例如狮子)可以被视为每种动物的“装饰”,它实际上可能不是唯一的(base.lion相同的 base.animal 记录可能存在 base.elephant 记录),因此您应该在某处添加唯一性约束。

现在,你不应该让 _inherit_inherits 都指向同一个父模型,这两个继承方案实际上是为了不同的目的,正如 OpenERP 中所解释的那样technical memento 。 相反,您可以在 animal.base 中使用代理方法,这些方法大致类似于您的 perform 方法,只不过它们需要找出子记录及其类型之外的 ID ,例如:

def emit_sound(self, cr, uid, ids, context=None):
    for this in self.browse(cr, uid, ids, context):
       animal_registry = self.pool['animal.%s' % this.type]
       animal_ids = animal_registry.search(cr, uid, 
           [('base_id','=',this.id)], context)
       assert len(animal_ids) == 1, 'Chimera alert! ;-)'
       animal_registry.emit_sound(cr, uid, animal_ids, context)

当然,您可以通过多种方式对其进行改进,例如将函数字段添加到 base.animal 中以自动化更多的管道工作。


另一方面,如果您确实不需要将 base.animal 存在于其他真实动物旁边,而只是需要一种方法来选择表单 View 中的任意动物,您可以尝试使用传统继承 _inherit + _name,其中 base.animal 是抽象基类为他们(没有实际持有任何记录)。 选择任意动物可以通过 fields.reference 来完成,您可以在其中过滤目标模型列表。 5.0 订阅模块包含an example with the doc_source field .
请注意,fields.reference 是一种混合体,不能与例如以下内容无缝集成: 浏览阅读搜索。它以 'model,id' 形式存储为字符串,每当您需要取消引用它时,您都必须手动拆分该值 - 因此,如果您选择该路径,请务必小心。它作为伪 many2one 集成的唯一位置是在客户端 UI 上,其他地方它只是一个简单的、哑的字符串值。

关于python - 在 OpenERP 中如何将继承对象视为子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14645832/

相关文章:

c++ - 使用 Python 访问 USB 硬件(具有 native C++ API 的压力传感器矩阵)

python - 如何制作Python 2轴 slider

python - 获取 Pandas 系列的最后一个完整序列

odoo - 如何在 openERP(odoo 8) 中更改语言

python - 如何从矩阵中的行中删除最小值 -

python - 我可以将 md5 身份验证与 psycopg2 一起使用吗?

python - 如何在 qweb 报告上增加公司 Logo 图像大小

python - 找不到可用的临时目录

css - 如何将 css 文件添加到 Odoo 中的自定义模块?

python - OpenERP安装问题