2014-09-26 1 views
4

Я определил следующие две odoo модель ORM:«отношение уже существует» после добавления Many2many поля в odoo

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 в моделях, проблема остается (конечно, имя отношения в сообщении об ошибке изменяется, чтобы отразить переименование), так что это не похоже на конфликт с некоторыми старыми отношениями, уже существующими в базе данных ,

ответ

10

Я понял это. Должен сказать, я считаю, что это технически квалифицируется как ошибка в 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 методе odoo's BaseModel.

Существует, однако, один улов. По умолчанию в indetifiers PostgreSQL (inluding идентификаторы индексов) can not be longer than 63 characters:

Система использует не более NAMEDATALEN-1 байт идентификатора; Более длинные имена могут быть записаны в командах, но они будут усечены. По умолчанию NAMEDATALEN равно 64, поэтому максимальная длина идентификатора составляет 63 байт.

Одуо не учитывает это.Он с радостью генерирует гораздо более длинные идентификаторы, которые затем усекаются PostgreSQL. Если оба идентификатора имеют одни и те же первые 63 символа (что для более длинных идентификаторов вполне вероятно), они будут обрабатываться PostgreSQL одинаково. Это означает, что первый индекс будет создан, но создание второго приведет к ошибке, так как он использует уже использованный идентификатор (по крайней мере, согласно PostgreSQL).

И что такое максимальная длина _name, может возникнуть проблема, если у вас возникли проблемы? Это зависит от того, сколько символов разделено между именами двух моделей в отношении m2m, но чтобы полностью избежать усечения идентификатора, вы никогда не должны использовать имена длиной более 16 символов.

Почему 16? Идентификаторы PostgreSQL не могут быть длиннее 63 символов. В индексных идентификаторах, генерируемых одуем, имеется 15 фиксированных символов. Это оставляет нам 48 символов, которые должны учитывать три повторения имен моделей. Это, в свою очередь, оставляет нас с 16 символами на одно имя модели.

Другим способом решения проблемы было бы вручную задать короткое имя отношения с помощью атрибута relation на поле Many2many.

+2

Я создал [билет о проблеме] (https://github.com/odoo/odoo/issues/2780) в системе отслеживания ошибок Odoo. –

+2

Отличная работа! В качестве обходного пути вы можете принудительно ввести имя для имени отношения, добавляющего в поле атрибут 'relation = '''. –

+0

Отличный улов! Сегодня я столкнулся с этой проблемой, так что кажется. – Yenthe

1

Я не вижу проблемы с вашим кодом. Возможно, вы попали в угловой футляр, ORM не может справиться хорошо, в результате или экспериментировать с несколькими вариантами отношения.

Возможно, работа с свежей инициализированной базой данных будет работать.

Если вы действительно хотите продолжить работу с текущей базой данных, вы можете попробовать удалить модуль и затем переустановить его. Это должно привести к тому, что его объекты базы данных будут удалены, а затем воссозданы.

И, наконец, это не работает, попробуйте вручную сбросить таблицы ludwik_offers в базу данных и обновить модуль таким образом, чтобы они были заново созданы.

+0

Нет, к сожалению, даже создание новой базы данных не работает. Я получаю то же точное сообщение при попытке установить модуль в новой базе данных, которую я только что создал. –

+0

Хорошо, я понял это сам и написал свой собственный ответ здесь. –