本文介绍了“关系已经存在"在 odoo 中添加 Many2many 字段后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've defined the following two odoo ORM models:

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 时,我收到以下消息:

When I try to start odoo I get the following message:

ProgrammingError: relation "ludwik_offers_duration_ludwik_offers_weekday_rel_ludwik_offers_" already exists

此外,当我更改模型中的 _name 属性时,问题仍然存在(当然错误消息中的关系名称会更改以反映重命名),因此这不仅仅是与数据库中已经存在一些旧关系.

Also, when I change the _name properties in models, the problem persists (of course the relation name in the error message changes to reflect the rename), so it's not like it's just a conflict with some old relations already existing in the database.

推荐答案

我想通了.我不得不说,我认为这在技术上属于 Odoo 中的一个错误.

I figured this out. I have to say, I think this technically qualifies as a bug in Odoo.

总结

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

The names of my models were too long. Every time you set a _name property longer than 16 characters you are setting yourself up to potentially experience this problem.

详情

当你创建一个 Many2many 关系时,odoo 会为这个关系建立一个新的数据库表,然后为该表创建两个数据库索引.他们的名字如下:

When you create a Many2many relation, odoo setts up a new database table for this relation and then creates two database indexes for the table. Their name are as follows:

  • __rel__id_index
  • __rel__id_index

其中 是适当模型的 _name 属性.你可以在odoo的BaseModel_m2m_raise_or_create_relation方法中观察到这一点.

Where <model1> and <model2> are the _name property of an appropriate model. You can observe this in _m2m_raise_or_create_relation method of odoo's BaseModel.

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

There is however one catch. By default indetifiers in PostgreSQL (inluding index identifiers) can not be longer than 63 characters:

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

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

Odoo doesn't take this into account. It happily generates much longer identifiers, which are then truncated by PostgreSQL. If both identifiers share the same first 63 characters (which for longer identifiers is quite likely) they will be treated by PostgreSQL as the same. That means the first index will be created, but creating the second one will result in an error, since it shares an identifier that was already used (at least according to PostgreSQL).

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

So what is the maximum length the _name property can have while avoiding the problem? It depends on how many characters are shared between the names of two models in m2m relation, but to fully avoid identifier truncation you should never use names longer than 16 characters.

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

Why 16? PostgreSQL identifiers can not be longer than 63 characters. In index identifiers generated by odoo there are 15 fixed characters. That leaves us with 48 characters, which have to accommodate three repetitions of model names. This in turn leaves us with 16 characters per single model name.

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

Another way to work around the issue would be to manually set a short relation name via relation attribute on the Many2many field.

这篇关于“关系已经存在"在 odoo 中添加 Many2many 字段后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 14:27