Как перезаписать метод onchange v7 с помощью нового API?

Я пытаюсь добавить некоторые функции в существующий метод onchange. Этот объявлен в v7, и я хочу использовать v8. Метод onchange_product_id модели stock.move.

Итак, я объявил свой метод onchange v8 (с тем же именем, что и у метода v7, который я хочу перезаписать). Я также повторно объявил затронутое поле product_id, потому что в противном случае мой метод onchange не вызывается (в переопределении я установил только имя сомодели, поскольку ожидается, что остальные атрибуты будут получены из исходного объявления).

Это мой код:

product_id = fields.Many2one(
    comodel_name='product.product',
)

@api.v8
@api.onchange('product_id')
def onchange_product_id(self):
    _logger.info('*' * 80)
    self.ensure_one()
    result = super(StockMove, self).onchange_product_id(
        self.product_id, self.location_id, self.location_dest_id,
        self.picking_id.partner_id)
    return result

Теперь проблема: я даже не вижу сообщения журнала, потому что получаю эту ошибку:

TypeError: объект «NoneType» не может быть вызван

Если я изменю декоратор @api.v8 и напишу вместо него @api.v7, я получу сообщение об ошибке, запрашивающее дополнительные аргументы в определении метода onchange.

Я также попытался заменить поле product_id в представлении XML, чтобы избежать вызова метода onchange с несколькими параметрами, но результат был тот же:

<field name="product_id" position="replace">
    <field name="product_id"/>
</field>

Старый XML-вызов метода таков:

<field name="product_id" on_change="onchange_product_id(product_id,location_id,location_dest_id, parent.partner_id)"/>

Кто-нибудь может мне помочь? Я нашел несколько вопросов, связанных с этим, в SO, но ответ не помог мне в этом случае.

Примечание. Я не хочу избегать Super и переводить весь код старого метода onchange в новый API. Это должен быть лучший способ управлять этим. Не так ли?


person forvas    schedule 17.10.2016    source источник
comment
@czoeliner прав... но это почти дубликат stackoverflow.com/questions/39366140/   -  person danidee    schedule 17.10.2016
comment
Я не думаю, что это дубликат или почти что, потому что здесь основное внимание уделяется механизму onchange при использовании нового API И старого API.   -  person CZoellner    schedule 18.10.2016


Ответы (1)


Так должно быть:

@api.multi
def onchange_product_id(
        self, product_id, location_id, location_dest_id, partner_id):
    self.ensure_one()
    result = super(StockMove, self).onchange_product_id(
        product_id, location_id, location_dest_id, partner_id)

    # your result manipulation here

    return result

Декоратор multi будет инкапсулировать параметры cr, uid, ids и context, поэтому вам понадобятся все остальные параметры. Возможно, вам понадобятся некоторые значения по умолчанию для последних параметров, но я не знаю исходного метода, поэтому не могу сказать.

person CZoellner    schedule 17.10.2016
comment
Спасибо @CZoellner. С этим кодом ошибок нет, но я не могу использовать преимущества декоратора v8 @api.onchange внутри метода. И из-за этого в конце метода мне придется обновить словарь value в переменной result, чтобы применить мои изменения (вместо self.my_field = 'my_value'). - person forvas; 17.10.2016
comment
Да, это правильно. Но старые методы onchange, к сожалению, не совместимы с новым API. - person CZoellner; 17.10.2016
comment
Какая беда тогда :( Большое спасибо за вашу помощь. - person forvas; 17.10.2016