iT邦幫忙

2021 iThome 鐵人賽

DAY 6
0
Software Development

Let's ODOO 開發與應用30天挑戰系列 第 6

Day6 Let's ODOO: Model(3) Decorators & Environment

依照昨天範例我們繼續寫下去

# -*- coding: utf-8 -*-

from odoo import api, models, fields
from odoo.exceptions import ValidationError

class ResStudent(models.Model):
    _name = 'res.student'
    _inherit = 'res.partner'
    _description = 'Student'

    nickname = fields.Char(string='綽號')
    math_score = fields.Float(string='數學成績')
    chinese_score = fields.Float(string='國文成績')
    avg_score = fields.Float(string='學期平均', compute='_compute_score')
    birthday = fields.Date(string='生日', required=True)
    school_id = fields.Many2one('res.company', string='所屬學校')
    school_city = fields.Char(string='所在城市', related='school_id.city')
    senior_id = fields.Many2one('res.student', string='直屬學長姐')
    junior_ids = fields.One2many('res.student', 'senior_id', string='直屬學弟妹')
    teacher_ids = fields.Many2many('res.partner', string='指導老師', domain=[('is_company', '!=', True)])
    gender = fields.Selection([("male", "男"), ("female", "女"), ("other", "其他")], string='性別')
    is_leadership = fields.Boolean(default=False)
    is_active = fields.Boolean(default=True)
    channel_ids = fields.Many2many('mail.channel', 'mail_channel_profile_partner', 'partner_id', 'channel_id', copy=False)



    @api.depends('math_score', 'chinese_score')
    def _compute_score(self):
        for record in self:
            record.avg_score = (record.math_score + record.chinese_score) / 2

    @api.onchange('school_id')
    def _onchange_shcool(self):
        for record in self:
            record.school_city = record.school_id.city

    @api.constrains('math_score', 'chinese_score')
    def _validate_score(self):
        for record in self:
            if record.math_score < 0 or record.chinese_score < 0:
                raise ValidationError(_("分數必須大於零"))

    @api.model
    def create(self, values):
        if values.get('is_active') is False:
            values.update({
                'is_leadership': False
            })
        return super(ResStudent, self).create(values)

Method decorators

透過ODOO提供的裝飾器來實現不同用途的方法,介紹常用的裝飾器

@api.constrains

規定fields要符合設定條件,否則無法新增或修改。

  @api.constrains('math_score', 'chinese_score')
  def _validate_score(self):
      for record in self:
          if record.math_score < 0 or record.chinese_score < 0:
              raise ValidationError(_("分數必須大於零"))

如範例所示,當其中一項分數小於零時便會報出錯誤提示,但要注意兩點,

  1. 此裝飾器無法控制relational field底下相關參數,例如我們限定teacher_id.mejor != math,老師科目不能等於數學,此裝飾器並不會有任何效果。
  2. 裝飾器只能限制view上的操作,如果是透過API方式新增進去,此裝飾限制器也無效。

@api.depends

常用於compute fields,當指定的field更改時會觸發method。

  @api.depends('math_score', 'chinese_score')
  def _compute_total(self):
      for record in self:
          record.avg_score = (record.math_score + record.chinese_score) / 2

當成績改變時,平均成績也會重新計算,同樣只作用於odoo view表層,直接更改的時候不會觸發。

@api.onchange

@api.depends 相似,當指定的field會觸發method

  @api.onchange('school_id')
  def _onchange_shcool(self):
      for record in self:
          record.school_city = record.school_id.city

當所選學校改變時,所在城市會跟著改變,有些要注意的地方:

  1. 只允許觸發同一個model底下的field,@api.depends 則沒有這個限制。
  2. 可以return一個dictionary,顯示提示視窗,以ODOO Document為例。
return {
    'warning': {'title': "Warning", 'message': "What is this?", 'type': 'notification'},
}
  1. one2manymany2many field 無法透過此方法修改。

@api.model

self代表Model本身,與model recordset無關的方法,如: create method

    @api.model
    def create(self, values):
        return super(ResPartner, self).create(values)

Environment

env裡存了許多快取可供使用者查詢及修改,日後也會透過此方法對DB做操作。

  • user: 目前使用的帳戶

    self.env.user
    
  • model: 獲取指定model

    self.env['res.partner'] #res_partner為model name
    
  • lang: 獲取當前語

    self.env.lang
    
  • company: 獲取當前company branch

    self.env.company
    
  • companies:獲取此user access的所有company branch

    self.env.companies
    

Decorators與Environment就介紹到這邊,明天我們來介紹model內的ORM method。


上一篇
Day5 Let's ODOO: Model(2) Fields
下一篇
Day7 Let's ODOO: Model(4) ORM API
系列文
Let's ODOO 開發與應用30天挑戰30

尚未有邦友留言

立即登入留言