Записи → Улучшенный аналог ondelete=restrict для полей many2many
По умолчанию у полей с типом many2many нет параметра ondelete, как у полей с типом many2one, который отвечает за то, что делать с элементом, который ссылается на другой элемент, если этот другой элемент удаляют.
У опции ondelete есть в таком случае два варианта:
cascade – удалять элемент при удалении родителя (не знаю как правильно назвать тот элемент, НА который ссылаются)
restrict – запрет удаления родительского элемента
Бывают случаи, когда для полей many2many тоже было бы неплохо использовать аналог опции ondelete=restrict. У меня как раз такой случай. Есть две модели – product.attribute и product.attribute.group, между которыми связь many2many.
Я переопределил метод unlink, внутри которого проверяю наличие связей у удаляемой записи. Ниже пример для проверки связей при попытке удаления product.attribute:
def unlink(self, cr, uid, ids, context=None): if context is None: context = {} for attribute in self.browse(cr, uid, ids): attribute_group = self.pool.get('product.attribute.group') attribute_group_ids = attribute_group.search(cr, uid, [('attribute_ids', 'in', attribute.id),]) if attribute_group_ids: attribute_group_names = [] for attribute_group_element in attribute_group.browse(cr, uid, attribute_group_ids): attribute_group_names.append(attribute_group_element.name) attribute_group_names_str = ', '.join(attribute_group_names) raise osv.except_osv(_('Some attribute groups have references to the attribute ') + attribute.name + '!', _('First remove these references: ') + attribute_group_names_str) return super(product_attribute_group, self).unlink(cr, uid, ids)
Аналогичный код написан и для проверки при попытке удаления product.attribute.group. Если находим ссылки на удаляемую запись, тогда формируем строку с перечислением записей, которые ссылаются на текущую, и выводим пользователю сообщение о том, что сначала нужно удалить эти ссылки. Таким образом пользователь сразу узнает, что конкретно мешает удалению текущей записи (кстати хорошо бы было сделать такое же сообщение и при ondelete=restrict, а то там просто выводится ошибка, а что конкретно нужно сделать чтобы все-таки удалить запись, не написано).
Вы можете заметить что тексты сообщения обрамлены в функцию _(), это для того чтобы строки были переводимыми. Чтобы эту функцию использовать, нужно подключить ее такой строкой:
from tools.translate import _
Вопросы и комментарии приветствуются.