"关系已经存在"在odoo中添加了Many2many字段之后

时间:2014-09-26 15:19:11

标签: python postgresql openerp relationship odoo

我已经定义了以下两个odoo ORM模型:

class Weekday(models.Model):
    _name = 'ludwik.offers.weekday'
    name = fields.Char()

class Duration(models.Model):
    _name = 'ludwik.offers.duration'
    weekday = fields.Many2many('ludwik.offers.weekday')

当我尝试启动odoo时,我收到以下消息:

ProgrammingError: relation "ludwik_offers_duration_ludwik_offers_weekday_rel_ludwik_offers_" already exists

此外,当我更改模型中的_name属性时,问题仍然存在(当然错误消息中的关系名称会更改以反映重命名),因此它不会像它一样“'只是与数据库中已存在的一些旧关系发生冲突。

2 个答案:

答案 0 :(得分:11)

我想出来了。我不得不说,我认为这在技术上有资格作为Odoo中的一个错误。

<强>摘要

我模特的名字太长了。每次设置_name属性超过16个字符时,您都可能会遇到此问题。

<强>详情

当您创建Many2many关系时,odoo会为此关系设置一个新的数据库表,然后为该表创建两个数据库索引。他们的名字如下:

  • <model1>_<model2>_rel_<model1>_id_index
  • <model1>_<model2>_rel_<model2>_id_index

<model1><model2>是适当模型的_name属性。您可以在_m2m_raise_or_create_relation BaseModel的{​​{1}}方法中观察到这一点。

然而有一个问题。默认情况下PostgreSQL中的整数(包括索引标识符)can not be longer than 63 characters

  

系统使用的标识符不超过NAMEDATALEN-1个字节;   较长的名称可以用命令编写,但它们会被截断。   默认情况下,NAMEDATALEN为64,因此最大标识符长度为63   字节。

Odoo没有考虑到这一点。它很乐意生成更长的标识符,然后被PostgreSQL截断。如果两个标识符共享相同的前63个字符(很可能是较长的标识符),它们将被PostgreSQL视为相同。这意味着将创建第一个索引,但创建第二个索引将导致错误,因为它共享一个已经使用的标识符(至少根据PostgreSQL)。

那么_name属性在避免问题时可以拥有的最大长度是多少?它取决于m2m关系中两个模型的名称之间共享的字符数,但为了完全避免标识符截断,你不应该使用超过16个字符的名称。

为什么16? PostgreSQL标识符不能超过63个字符。在odoo生成的索引标识符中,有15个固定字符。这留下了48个字符,这些字符必须容纳三个重复的模型名称。这反过来使我们每个型号名称留下16个字符。

解决此问题的另一种方法是通过relation字段上的Many2many属性手动设置短关系名称。

答案 1 :(得分:1)

我的代码没有看到任何问题。也许你到达角落的情况下,ORM无法处理好,结果或试验了几种关系的变化。

尝试使用刚刚初始化的数据库可能会有效。

如果您真的想继续使用当前数据库,可以尝试卸载模块然后重新安装。这应该删除它然后重新创建它的数据库对象。

最后,它不起作用,尝试手动删除数据库中的ludwik_offers表并升级您的模块,以便重新创建它。