到目前为止,字段都是直接存储在数据库中,并直接从数据库中检索。字段也可以计算。在这种情况下,字段的值不是从数据库中检索的,而是通过调用模型的方法实时计算的。
要创建计算字段,请创建字段并将其属性compute设置为方法名。计算方法应该在每个记录的self中设置要计算的字段值。

注意:self是一个集合
对象本身是一个记录集,即记录的有序集合。它支持集合上的标准Python操作,如len(self)iter(self),以及额外的集合操作,如recs1 + recs2
self上迭代会一个接一个地给出记录,其中每个记录本身就是一个大小为1的集合。您可以使用点符号访问/分配单个记录上的字段,比如record.name

import random
from odoo import models, fields, api

class ComputedModel(models.Model):
    _name = 'test.computed'

    name = fields.Char(compute='_compute_name')

    def _compute_name(self):
        for record in self:
            record.name = str(random.randint(1, 1e6))

依赖

计算字段的值通常取决于记录上的其他字段的值。ORM希望开发人员使用修饰符depends()指定对计算方法的依赖关系。每当它的一些依赖项被修改时,ORM使用给定的依赖项来触发字段的重新计算:

from odoo import models, fields, api

class ComputedModel(models.Model):
    _name = 'test.computed'

    name = fields.Char(compute='_compute_name')
    value = fields.Integer()

    @api.depends('value')
    def _compute_name(self):
        for record in self:
            record.name = "Record with value %s" % record.value

“计算字段”练习
将占用席位的百分比添加到会话模型中
在树视图和表单视图中显示该字段
将该字段显示为进度条
将计算字段添加到会话
在会话视图中显示字段:

openacademy/models.py

    course_id = fields.Many2one('openacademy.course',
        ondelete='cascade', string="Course", required=True)
    attendee_ids = fields.Many2many('res.partner', string="Attendees")

    taken_seats = fields.Float(string="Taken seats", compute='_taken_seats')

    @api.depends('seats', 'attendee_ids')
    def _taken_seats(self):
        for r in self:
            if not r.seats:
                r.taken_seats = 0.0
            else:
                r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats

openacademy/views/openacademy.xml

                                <field name="start_date"/>
                                <field name="duration"/>
                                <field name="seats"/>
                                <field name="taken_seats" widget="progressbar"/>
                            </group>
                        </group>
                        <label for="attendee_ids"/>
                <tree string="Session Tree">
                    <field name="name"/>
                    <field name="course_id"/>
                    <field name="taken_seats" widget="progressbar"/>
                </tree>
            </field>
        </record>

默认值

可以给任何字段一个默认值。在字段定义中,添加default=X选项,其中X可以是Python字面值(boolean、integer、float、string),也可以是接受记录集并返回值的函数:

name = fields.Char(default="Unknown")
user_id = fields.Many2one('res.users', default=lambda self: self.env.user)

self.env允许访问请求参数和其他有用的东西:
self.env.crself._cr是数据库游标对象;它用于查询数据库
self.env.uidself._uid是当前用户的数据库id
self.env.user是当前用户的记录
self.env.contextself._context是上下文字典
self.env.ref(xml_id)返回与XML id对应的记录
self.env[model_name]返回给定模型的实例

“活动对象——默认值”练习
将start_date的默认值定义为today。
在类会话中添加active字段,并在默认情况下将会话设置为活动。

openacademy/models.py

    _description = "OpenAcademy Sessions"

    name = fields.Char(required=True)
    start_date = fields.Date(default=fields.Date.today)
    duration = fields.Float(digits=(6, 2), help="Duration in days")
    seats = fields.Integer(string="Number of seats")
    active = fields.Boolean(default=True)

    instructor_id = fields.Many2one('res.partner', string="Instructor",
        domain=['|', ('instructor', '=', True),

openacademy/views/openacademy.xml

                                <field name="course_id"/>
                                <field name="name"/>
                                <field name="instructor_id"/>
                                <field name="active"/>
                            </group>
                            <group string="Schedule">
                                <field name="start_date"/>

Odoo有内置规则active字段,设置为False使记录隐藏。