Call onchange methods on the server side

The Create new records and Update values of a recordset record recipes in Chapter 5, Basic Server Side Development, mentioned that these operations did not call onchange methods automatically. Yet in a number of cases it is important that these operations are called because they update important fields in the created or updated record. Of course, you can do the required computation yourself, but this is not always possible as the onchange method can be added or modified by a third-party addon module installed on the instance that you don't know about.

This recipe explains how to call the onchange methods on a record by manually playing the onchange method before creating a record.

Getting ready

We will reuse the settings from the preceding recipe, Write onchange methods. The action will take place in a new method of library.member called return_all_books(self).

How to do it…

In this recipe, we will manually create a record of the library.returns.wizard model, and we want the onchange method to compute the returned books for us. To do this, you need to perform the following steps:

  1. Create the method return_all_books in the LibraryMember class:
        @api.multi
        def return_all_books(self):
            self.ensure_one
  2. Get an empty recordset for library.returns.wizard:
            wizard = self.env['library.returns.wizard']
  3. Prepare the values to create a new wizard record:
            values = {'member_id': self.id, book_ids=False}
  4. Retrieve the onchange specifications for the wizard:
            specs = wizard._onchange_spec()
  5. Get the result of the onchange method:
            updates = wizard.onchange(values, ['member_id'], specs)
  6. Merge these results with the values of the new wizard:
            value = updates.get('value', {})
            for name, val in value.iteritems():
                if isinstance(val, tuple):
                    value[name] = val[0]
            values.update(value)
  7. Create the wizard:
            record = wizard.create(values)

How it works…

For an explanation of step 1 to step 3, please refer to the recipe Create new records in Chapter 5, Basic Server Side Development.

Step 4 calls the _onchange_spec method on the model, passing no argument. This method will retrieve the updates that are triggered by the modification of which other field. It does this by examining the form view of the model (remember, onchange methods are normally called by the web client).

Step 5 calls the onchange(values, field_name, field_onchange) method of the model with 3 arguments:

  • values: The list of values we want to set on the record. You need to provide a value for all the fields you expect to be modified by the onchange method. In the recipe, we set book_ids to False for this reason.
  • field_name: A list of fields for which we want to trigger the onchange methods. You can pass an empty list, and it will use the fields defined in values. However, you will often want to specify that list manually to control the order of evaluation, in case different fields can update a common field.
  • field_onchange: The onchange specifications that were computed in step 4. This method finds out which onchange methods must be called and in what order and returns a dictionary, which can contain the following keys:
    • value: This is a dictionary of newly computed field values. This dictionary only features keys that are in the values parameter passed to onchange(). Note that Many2one fields are mapped to a tuple containing (id, display_name) as an optimization for the web client.
    • warning: This is a dictionary containing a warning message that the web client will display to the user.
    • domain: This is a dictionary mapping field names to new validity domains.

Generally, when manually playing onchange methods, we only care about what is in value.

Step 6 updates our initial values dictionary with the values computed by the onchange. We process the values corresponding to Many2one fields to only keep the id. To do so, we take advantage of the fact that these fields are only those whose value is returned as a tuple.

Step 7 finally creates the record.

There's more…

If you need to call an onchange method after modifying a field, the code is the same. You just need to get a dictionary for the values of the record, which can be obtained by using values = dict(record._cache) after modifying the field.

See also

  • The Create new records and Update values of recordset records recipes in Chapter 5, Basic Server Side Development
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.137.127