Odoo自帶的api裝飾器主要有:model,multi,one,constrains,depends,onchange,returns 七個裝飾器。
multi
multi則指self是多個記錄的合集。是以,常使用for—in語句周遊self。
multi通常用于:在tree視圖中點選多條記錄,然後執行某方法,那麼那個方法必須用@api.multi修飾,而參數中的self則代表選中的多條記錄。
如果僅僅是在form視圖下操作,那麼self中通常隻有目前正在操作的記錄。
@api.multi
@api.depends('order_line.customer_lead', 'confirmation_date', 'order_line.state')
def _compute_expected_date(self):
""" For service and consumable, we only take the min dates. This method is extended in sale_stock to
take the picking_policy of SO into account.
"""
for order in self:
dates_list = []
confirm_date = fields.Datetime.from_string(order.confirmation_date if order.state == 'sale' else fields.Datetime.now())
for line in order.order_line.filtered(lambda x: x.state != 'cancel' and not x._is_delivery()):
dt = confirm_date + timedelta(days=line.customer_lead or 0.0)
dates_list.append(dt)
if dates_list:
order.expected_date = fields.Datetime.to_string(min(dates_list))
@api.multi
def write(self, vals):
res = super(Employee, self).write(vals)
return res
@api.multi
def unlink(self):
resources = self.mapped('resource_id')
super(Employee, self).unlink()
return resources.unlink()
model:方法裡不寫預設是:model
此時的self僅代表模型本身,不含任何記錄資訊。
@api.model
def create(self, vals):
if vals.get('name', _('New')) == _('New'):
if 'company_id' in vals:
vals['name'] = self.env['ir.sequence'].with_context(force_company=vals['company_id']).next_by_code('sale.order') or _('New')
else:
vals['name'] = self.env['ir.sequence'].next_by_code('sale.order') or _('New')
# Makes sure partner_invoice_id', 'partner_shipping_id' and 'pricelist_id' are defined
if any(f not in vals for f in ['partner_invoice_id', 'partner_shipping_id', 'pricelist_id']):
partner = self.env['res.partner'].browse(vals.get('partner_id'))
addr = partner.address_get(['delivery', 'invoice'])
vals['partner_invoice_id'] = vals.setdefault('partner_invoice_id', addr['invoice'])
vals['partner_shipping_id'] = vals.setdefault('partner_shipping_id', addr['delivery'])
vals['pricelist_id'] = vals.setdefault('pricelist_id', partner.property_product_pricelist and partner.property_product_pricelist.id)
result = super(SaleOrder, self).create(vals)
return result
constrains
字段的代碼限制。
@api.constrains('parent_id')
def _check_parent_id(self):
for employee in self:
if not employee._check_recursion():
raise ValidationError(_('You cannot create a recursive hierarchy.'))
depends
depends 主要用于compute方法,depends就是用來标該方法依賴于哪些字段的。
@api.depends('parent_group', 'parent_group.users', 'groups', 'groups.users', 'explicit_users')
def _compute_users(self):
for record in self:
users = record.mapped('groups.users')
users |= record.mapped('explicit_users')
users |= record.mapped('parent_group.users')
record.update({'users': users, 'count_users': len(users)})
@api.depends('order_line.price_total')
def _amount_all(self):
"""
Compute the total amounts of the SO.
"""
for order in self:
amount_untaxed = amount_tax = 0.0
for line in order.order_line:
amount_untaxed += line.price_subtotal
amount_tax += line.price_tax
order.update({
'amount_untaxed': order.pricelist_id.currency_id.round(amount_untaxed),
'amount_tax': order.pricelist_id.currency_id.round(amount_tax),
'amount_total': amount_untaxed + amount_tax,
})
onchange
onchange的使用方法非常簡單,就是當字段發生改變時,觸發綁定的函數。
@api.onchange('team_type')
def _onchange_team_type(self):
if self.team_type == 'sales':
self.use_quotations = True
self.use_invoices = True
if not self.dashboard_graph_model:
self.dashboard_graph_model = 'sale.report'
else:
self.use_quotations = False
self.use_invoices = False
self.dashboard_graph_model = 'sale.report'
return super(CrmTeam, self)._onchange_team_type()
returns
returns的用法主要是用來指定傳回值的格式,它接受三個參數,第一個為傳回值的model,第二個為向下相容的method,第三個為向上相容的method
@api.returns('self')
def _default_employee_get(self):
return self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
@api.model
@api.returns('self', lambda value: value.id if value else False)
def _get_default_team_id(self, user_id=None):
if not user_id:
user_id = self.env.uid
company_id = self.sudo(user_id).env.user.company_id.id
team_id = self.env['crm.team'].sudo().search([
'|', ('user_id', '=', user_id), ('member_ids', '=', user_id),
'|', ('company_id', '=', False), ('company_id', 'child_of', [company_id])
], limit=1)
if not team_id and 'default_team_id' in self.env.context:
team_id = self.env['crm.team'].browse(self.env.context.get('default_team_id'))
if not team_id:
default_team_id = self.env.ref('sales_team.team_sales_department', raise_if_not_found=False)
if default_team_id:
try:
default_team_id.check_access_rule('read')
except AccessError:
return self.env['crm.team']
if self.env.context.get('default_type') != 'lead' or default_team_id.use_leads and default_team_id.active:
team_id = default_team_id
return team_id
one
one的用法主要用于self為單一記錄的情況,意思是指:self僅代表目前正在操作的記錄。
@api.one
def _compute_amount_undiscounted(self):
total = 0.0
for line in self.order_line:
total += line.price_subtotal + line.price_unit * ((line.discount or 0.0) / 100.0) * line.product_uom_qty # why is there a discount in a field named amount_undiscounted ??
self.amount_undiscounted = total