在odoo中添加Many2many字段后"relation already exists"



我定义了以下两个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属性时,问题仍然存在(当然,错误消息中的关系名称会更改以反映重命名),因此这并不只是与数据库中已经存在的一些旧关系的冲突。

我想明白了。我不得不说,我认为这在技术上符合奥多奥的缺陷。

摘要

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

详细信息

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

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

其中<model1><model2>是适当模型的_name性质。你可以在奥多的BaseModel_m2m_raise_or_create_relation方法中观察到这一点。

然而,有一个问题。默认情况下,PostgreSQL中的标识符(包括索引标识符)不能超过63个字符:

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

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

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

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

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

我认为您的代码没有任何问题。也许你遇到了一个ORM无法很好处理的角落案例,或者尝试了这种关系的几种变体。

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

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

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

相关内容

最新更新