在OpenERP中,如何在安装模块时强制SQL运行?

时间:2012-05-29 20:36:30

标签: openerp

我有一个内置在OpenERP中的模块,可以为现有模型添加一些字段。

定义大致如下:

class res_partner(osv.osv):
    _name = _inherit = 'res.partner'
    _columns = {
        'my_special_id': fields.integer('Special ID', required=False, readonly=True),
    }
    _defaults = {
        'my_special_id': lambda *a: None
    }

    _sql_constraints = [
        ('special_id_uniq', 'UNIQUE (my_special_id)', 'Must be unique.'),
    }

    _sql = """CREATE UNIQUE INDEX special_id_limited_uniq
            ON res_partner (my_special_id)
            WHERE my_special_id != 0
    """
res_partner()

我的目标是拥有一个字段(special_id_uniq):

  1. 默认为NULL
  2. 是一个整数
  3. 在所有值中都是唯一的,除了NULL
  4. 我的第一直觉是创建上面的_sql_constraint定义,但是这导致了问题:显然OpenERP没有可空的整数字段,因此'None'被视为0.这打破了SQL约束,因为现在多个值为0必须被允许。

    为了解决这个问题,我删除了模型上的_sql_constraints选项,并添加了创建PostgreSQL部分索引的_sql代码。为了验证它是否有效,我在PostgreSQL上自己运行了SQL,它实现了我想要的效果。但是,当我通过OpenERP创建一个新数据库并安装我的自定义模块时,不会运行此SQL。那是因为没有创建模型:

    def _auto_init(self, cr, context=None):
        #...
        create = not self._table_exist(cr)
        #...
        #Line 3046 of openerp/osv/orm.py version 6.1 function _auto_init
        if create:
            self._execute_sql(cr)
        #...
    

    那么,如何在模块安装时运行一些自定义SQL?

2 个答案:

答案 0 :(得分:4)

实际上,我可能刚刚回答了我自己的问题:覆盖_auto_init。

编辑:

是的,以下工作在安装/升级期间运行SQL:

def _auto_init(self, cr, context=None):
    ret = super(res_partner, self)._auto_init(cr, context)
    self._execute_sql(cr)
    return ret

答案 1 :(得分:3)

您可以通过在模块的数据xml文件中添加function条目来实现此目的。

<openerp>
  <data>
    <!-- ... your init data records ...-->
    <function model="res.partner" name="_my_init_mehod"/>
  </data>
</openerp>

您可以在标准模块document中看到相关的工作示例: document_data.xml声明调用函数_attach_parent_id,以便在安装结束时将所有附件迁移到新的DMS结构。