Skip to Content

Contributors

How to use @api.onchange in models.AbstractModel, when the interiting class field name are different.

Dear all,

I have one technical challenge while doing this PR -> https://github.com/OCA/account-analytic/pull/251

In the origin module, there was abstract class,

class AnalyticDimensionLine(models.AbstractModel):
    _name = 'analytic.dimension.line'

Which are inherited by other model, i.e., account.move.line, account.invoice.line, etc.

class AccountInvoiceLine(models.Model):
    _name = 'account.invoice.line'
    _inherit = ['analytic.dimension.line', 'account.invoice.line']
    _analytic_tag_field_name = 'analytic_tag_ids'

Now, I wanted to add api.onchange method on a field which can be varied by each inheriting model via _analytic_tag_field_name

Question is, I would want to do the onchange on the base abstract class, analytic.dimension.line like this, but it doesn't work.

class AnalyticDimensionLine(models.AbstractModel):
    _inherit = 'analytic.dimension.line'

    @api.onchange(lambda self: self._analytic_tag_field_name)      ---------------------> THIS NOT WORK
    def _onchange_analytic_tag_ids(self):

And so, I end up having to add @api.onchange in inheriting models. Which I think not very good.

class AccountInvoiceLine(models.Model):
    _inherit = 'account.invoice.line'

    @api.onchange('analytic_tag_ids')  ----------------------> NOT GOOD
    def _onchange_analytic_tag_ids(self):


Any thought are appreciated,
Than you,




by Kitti Upariphutthiphong - 01:31 - 27 Sep 2019

Follow-Ups

  • Re: How to use @api.onchange in models.AbstractModel, when the interiting class field name are different.
    Hello Simone,

    Thank you for answer. I did try that with,

    @api.onchange(lambda self: self._get_onchange_analytic_tag_spec)
    also
    @api.onchange(lambda self: (self._analytic_tag_field_name, ))

    But it do not triggered.

    Just FYI. from the existing Odoo source code, I only see some @api.depends that call other function.

    Kitti


    On Mon, Oct 7, 2019 at 2:42 PM Simone Orsi <simahawk@gmail.com> wrote:
    Hi Kitti,

    AFAIS your solution with the lambda probably does not work because you are returning the field name instead of a tuple/list of fields.

    If you want to do it that way I suggest you use a specific method in the base model, eg:

    class AccountInvoiceLine(models.Model):
        _name = 'account.invoice.line'
        _inherit = ['analytic.dimension.line', 'account.invoice.line']
        _analytic_tag_field_name = 'analytic_tag_ids'

     def _get_onchange_analytic_tag_spec(self):
        return (self._analytic_tag_field_name, )

    @api.onchange(self._get_onchange_analytic_tag_spec)
        def _onchange_analytic_tag_ids(self):
        [...]

    Hope this helps. Bests,
    S.


    On Fri, Sep 27, 2019 at 1:31 PM Kitti Upariphutthiphong <kittiu@ecosoft.co.th> wrote:
    Dear all,

    I have one technical challenge while doing this PR -> https://github.com/OCA/account-analytic/pull/251

    In the origin module, there was abstract class,

    class AnalyticDimensionLine(models.AbstractModel):
        _name = 'analytic.dimension.line'

    Which are inherited by other model, i.e., account.move.line, account.invoice.line, etc.

    class AccountInvoiceLine(models.Model):
        _name = 'account.invoice.line'
        _inherit = ['analytic.dimension.line', 'account.invoice.line']
        _analytic_tag_field_name = 'analytic_tag_ids'

    Now, I wanted to add api.onchange method on a field which can be varied by each inheriting model via _analytic_tag_field_name

    Question is, I would want to do the onchange on the base abstract class, analytic.dimension.line like this, but it doesn't work.

    class AnalyticDimensionLine(models.AbstractModel):
        _inherit = 'analytic.dimension.line'

        @api.onchange(lambda self: self._analytic_tag_field_name)      ---------------------> THIS NOT WORK
        def _onchange_analytic_tag_ids(self):

    And so, I end up having to add @api.onchange in inheriting models. Which I think not very good.

    class AccountInvoiceLine(models.Model):
        _inherit = 'account.invoice.line'

        @api.onchange('analytic_tag_ids')  ----------------------> NOT GOOD
        def _onchange_analytic_tag_ids(self):


    Any thought are appreciated,
    Than you,



    _______________________________________________
    Mailing-List: https://odoo-community.org/groups/contributors-15
    Post to: mailto:contributors@odoo-community.org
    Unsubscribe: https://odoo-community.org/groups?unsubscribe

    _______________________________________________
    Mailing-List: https://odoo-community.org/groups/contributors-15
    Post to: mailto:contributors@odoo-community.org
    Unsubscribe: https://odoo-community.org/groups?unsubscribe


    by Kitti Upariphutthiphong - 10:45 - 9 Oct 2019
  • Re: How to use @api.onchange in models.AbstractModel, when the interiting class field name are different.
    Hi Kitti,

    AFAIS your solution with the lambda probably does not work because you are returning the field name instead of a tuple/list of fields.

    If you want to do it that way I suggest you use a specific method in the base model, eg:

    class AccountInvoiceLine(models.Model):
        _name = 'account.invoice.line'
        _inherit = ['analytic.dimension.line', 'account.invoice.line']
        _analytic_tag_field_name = 'analytic_tag_ids'

     def _get_onchange_analytic_tag_spec(self):
        return (self._analytic_tag_field_name, )

    @api.onchange(self._get_onchange_analytic_tag_spec)
        def _onchange_analytic_tag_ids(self):
        [...]

    Hope this helps. Bests,
    S.


    On Fri, Sep 27, 2019 at 1:31 PM Kitti Upariphutthiphong <kittiu@ecosoft.co.th> wrote:
    Dear all,

    I have one technical challenge while doing this PR -> https://github.com/OCA/account-analytic/pull/251

    In the origin module, there was abstract class,

    class AnalyticDimensionLine(models.AbstractModel):
        _name = 'analytic.dimension.line'

    Which are inherited by other model, i.e., account.move.line, account.invoice.line, etc.

    class AccountInvoiceLine(models.Model):
        _name = 'account.invoice.line'
        _inherit = ['analytic.dimension.line', 'account.invoice.line']
        _analytic_tag_field_name = 'analytic_tag_ids'

    Now, I wanted to add api.onchange method on a field which can be varied by each inheriting model via _analytic_tag_field_name

    Question is, I would want to do the onchange on the base abstract class, analytic.dimension.line like this, but it doesn't work.

    class AnalyticDimensionLine(models.AbstractModel):
        _inherit = 'analytic.dimension.line'

        @api.onchange(lambda self: self._analytic_tag_field_name)      ---------------------> THIS NOT WORK
        def _onchange_analytic_tag_ids(self):

    And so, I end up having to add @api.onchange in inheriting models. Which I think not very good.

    class AccountInvoiceLine(models.Model):
        _inherit = 'account.invoice.line'

        @api.onchange('analytic_tag_ids')  ----------------------> NOT GOOD
        def _onchange_analytic_tag_ids(self):


    Any thought are appreciated,
    Than you,



    _______________________________________________
    Mailing-List: https://odoo-community.org/groups/contributors-15
    Post to: mailto:contributors@odoo-community.org
    Unsubscribe: https://odoo-community.org/groups?unsubscribe


    by Simone Orsi - 09:41 - 7 Oct 2019
  • Re: How to use @api.onchange in models.AbstractModel, when the interiting class field name are different.
    Hello Pedro,

    Thank you! It resolved partly, but still having to have this api.onchange on every model though.

    Note: I have heard a word from Rafael Odoo that, Odoo are on the way of removing api.onchange, and make api.depends more abstract in the future. May be I have to wait till then...

    Kitti

    On Fri, Oct 4, 2019 at 10:31 AM Pedro M. Baeza (Tecnativa) <pedro.baeza@tecnativa.com> wrote:
    Hi, Kitti, what you can do is:


    class BaseModel(models.AbstractModel):
        _name = 'base.model'
        def _onchange_field_base(self, field_name):
            ... # do whatever with field_name


    class SpecificModel(models.Model):
        _inherit = 'base.model'
        _name = 'specific.model'

        @api.onchange('specific_field')
        def _onchange_specific_field(self):
            return self._onchange_field_base('specific_field')

    Regards.

    El vie., 27 sept. 2019 a las 13:31, Kitti Upariphutthiphong (<kittiu@ecosoft.co.th>) escribió:
    Dear all,

    I have one technical challenge while doing this PR -> https://github.com/OCA/account-analytic/pull/251

    In the origin module, there was abstract class,

    class AnalyticDimensionLine(models.AbstractModel):
        _name = 'analytic.dimension.line'

    Which are inherited by other model, i.e., account.move.line, account.invoice.line, etc.

    class AccountInvoiceLine(models.Model):
        _name = 'account.invoice.line'
        _inherit = ['analytic.dimension.line', 'account.invoice.line']
        _analytic_tag_field_name = 'analytic_tag_ids'

    Now, I wanted to add api.onchange method on a field which can be varied by each inheriting model via _analytic_tag_field_name

    Question is, I would want to do the onchange on the base abstract class, analytic.dimension.line like this, but it doesn't work.

    class AnalyticDimensionLine(models.AbstractModel):
        _inherit = 'analytic.dimension.line'

        @api.onchange(lambda self: self._analytic_tag_field_name)      ---------------------> THIS NOT WORK
        def _onchange_analytic_tag_ids(self):

    And so, I end up having to add @api.onchange in inheriting models. Which I think not very good.

    class AccountInvoiceLine(models.Model):
        _inherit = 'account.invoice.line'

        @api.onchange('analytic_tag_ids')  ----------------------> NOT GOOD
        def _onchange_analytic_tag_ids(self):


    Any thought are appreciated,
    Than you,



    _______________________________________________
    Mailing-List: https://odoo-community.org/groups/contributors-15
    Post to: mailto:contributors@odoo-community.org
    Unsubscribe: https://odoo-community.org/groups?unsubscribe

    _______________________________________________
    Mailing-List: https://odoo-community.org/groups/contributors-15
    Post to: mailto:contributors@odoo-community.org
    Unsubscribe: https://odoo-community.org/groups?unsubscribe


    by Kitti Upariphutthiphong - 06:56 - 7 Oct 2019
  • Re: How to use @api.onchange in models.AbstractModel, when the interiting class field name are different.
    Hi, Kitti, what you can do is:


    class BaseModel(models.AbstractModel):
        _name = 'base.model'
        def _onchange_field_base(self, field_name):
            ... # do whatever with field_name


    class SpecificModel(models.Model):
        _inherit = 'base.model'
        _name = 'specific.model'

        @api.onchange('specific_field')
        def _onchange_specific_field(self):
            return self._onchange_field_base('specific_field')

    Regards.

    El vie., 27 sept. 2019 a las 13:31, Kitti Upariphutthiphong (<kittiu@ecosoft.co.th>) escribió:
    Dear all,

    I have one technical challenge while doing this PR -> https://github.com/OCA/account-analytic/pull/251

    In the origin module, there was abstract class,

    class AnalyticDimensionLine(models.AbstractModel):
        _name = 'analytic.dimension.line'

    Which are inherited by other model, i.e., account.move.line, account.invoice.line, etc.

    class AccountInvoiceLine(models.Model):
        _name = 'account.invoice.line'
        _inherit = ['analytic.dimension.line', 'account.invoice.line']
        _analytic_tag_field_name = 'analytic_tag_ids'

    Now, I wanted to add api.onchange method on a field which can be varied by each inheriting model via _analytic_tag_field_name

    Question is, I would want to do the onchange on the base abstract class, analytic.dimension.line like this, but it doesn't work.

    class AnalyticDimensionLine(models.AbstractModel):
        _inherit = 'analytic.dimension.line'

        @api.onchange(lambda self: self._analytic_tag_field_name)      ---------------------> THIS NOT WORK
        def _onchange_analytic_tag_ids(self):

    And so, I end up having to add @api.onchange in inheriting models. Which I think not very good.

    class AccountInvoiceLine(models.Model):
        _inherit = 'account.invoice.line'

        @api.onchange('analytic_tag_ids')  ----------------------> NOT GOOD
        def _onchange_analytic_tag_ids(self):


    Any thought are appreciated,
    Than you,



    _______________________________________________
    Mailing-List: https://odoo-community.org/groups/contributors-15
    Post to: mailto:contributors@odoo-community.org
    Unsubscribe: https://odoo-community.org/groups?unsubscribe


    by Pedro M. Baeza - 10:31 - 4 Oct 2019