Fields can have values calculated by a function, instead of simply reading a database stored value. A computed field is declared just like a regular field, but has the additional compute argument defining the function used to calculate it.

In most cases computed fields involve writing some business logic, so we will develop this topic more in Chapter 7, ORM Application Logic - Supporting Business Processes. We will still explain them here, but will keep the business logic side as simple as possible.

Let's work on an example: Stages have a fold field. We will add to To-do Tasks a computed field with the Folded? flag for the corresponding Stage.

We should edit the TodoTask model in the todo_model.py file to add the following:

# class TodoTask(models.Model):
    stage_fold = fields.Boolean(
        'Stage Folded?',
        compute='_compute_stage_fold')

    @api.depends('stage_id.fold')
    def _compute_stage_fold(self):
        for task in self:
            task.stage_fold = task.stage_id.fold

The preceding code adds a new stage_fold field and the _compute_stage_fold method used to compute it. The function name was passed as a string, but it's also allowed to pass it as a callable reference (the function identifier with no quotes). In this case we should make sure the function is defined in the Python file before the field is.

The @api.depends decorator is needed when the computation depends on other fields, as it usually does. It lets the server know when to recompute stored or cached values. One or more field names are accepted as arguments and dot-notation can be used to follow field relationships.

The computation function is expected to assign a value to the field or fields to compute. If it doesn't, it will error. Since self is a record object, our computation here is simply to get the Folded? field using stage_id.fold. The result is achieved by assigning that value (writing it) to the computed field, stage_fold.

We won't be working yet on the views for this module, but you can make right now a quick edit on the task form to confirm if the computed field is working as expected: using the Developer Mode pick the Edit View option and add the field directly in the form XML. Don't worry: it will be replaced by the clean module view on the next upgrade.