我已经定义了以下两个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
属性时,问题仍然存在(当然错误消息中的关系名称会更改以反映重命名),因此它不会像它一样“'只是与数据库中已存在的一些旧关系发生冲突。
答案 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
表并升级您的模块,以便重新创建它。