Улучшенный аналог 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 _


Вопросы и комментарии приветствуются.

Оригинал статьи: http://dskarataev.ru/2012/05/uluchshennyj-analog-ondeleterestrict-dlya-polej-many2many/

0 комментариев

Оставить комментарий