第二十一章 默认值
我们在第二部分提到过,odoo在获取字段默认值的过程大致可以分为如下四个部分:
首先从当前代码的上下文(context)中寻找默认值(default_)开头的部分,如果找到则使用找到的值作为默认值,否则进行第2步查找。
从用户自定义的默认值(ir.default)表中进行查找,查到则使用,否则进行第3步的查找。
从字段定义的属性中进行查找,即我们常使用的default属性。如果有值,则使用。否则进行第4步的查找。
从父类对象的默认值设置中进行查找。
其实这个过程中我们遗漏了很重要的一部分细节,即对于那些依赖公司的字段的默认值设置,对于这类字段的默认值来说,其实别有洞天。本章将详细介绍,依赖于公司的字段(company_dependent)的默认值设置。
从一个问题说起
我们知道,在合作伙伴对象(res.partner)中,有两个会计科目:应收账款(property_account_receivable_id)和应付账款(property_account_payable_id),这两个字段有如下两个行为:
- 与公司相关,不同公司可以设置不同的值。
- 新建合作伙伴时,会自动设置默认值。
OK,看起来好像没什么特别,接下来我们来看这两个字段的定义。
property_account_receivable_id = fields.Many2one('account.account', company_dependent=True,
string="Account Receivable",
domain="[('account_type', '=', 'asset_receivable'), ('deprecated', '=', False), ('company_id', '=', current_company_id)]",
help="This account will be used instead of the default one as the receivable account for the current partner",
required=True)
property_account_position_id = fields.Many2one('account.fiscal.position', company_dependent=True,
string="Fiscal Position",
domain="[('company_id', '=', current_company_id)]",
help="The fiscal position determines the taxes/accounts used for this contact.")
我们发现,在他俩个的字段定义中并没有default的设置属性。根据我们前面的结论,我们输出了合作伙伴创建时的上下文,也没有发现相关默认值设置。虽然我们在用户自定义默认值中找到了默认值的设置,但是并不能解释我们遇到的问题,因为当我们清空了用户自定义默认值后,我们发现新建合作伙伴依旧能够带出默认值。
特殊的默认值
我们在公司相关字段的设置中发现了一个特别的方法:
def _default_company_dependent(self, model):
return model.env['ir.property'].get(self.name, self.model_name)
我们发现,对于公司相关的字段来说,不指定default属性的时候,会使用\default_company_dependent方法来填充默认值。
我们知道,公司关联字段的值存储在ir.property对象中,那么理所当然,默认值应该也从ir.property中获取。
@api.model
def get(self, name, model, res_id=False):
if not res_id:
t, v = self._get_default_property(name, model)
if not v or t != 'many2one':
return v
return self.env[v[0]].browse(v[1])
p = self._get_property(name, model, res_id=res_id)
if p:
return p.get_by_record()
return False
我们从ir.property的get方法中可以看到,如果我们传入了资源id,那么将使用表中已有的res_id值作为默认值。 而对于没有传入的资源ID的情况,则要使用默认的方法_get_default_property方法来获取值。
# only cache Property.get(res_id=False) as that's
# sub-optimally.
COMPANY_KEY = "self.env.context.get('force_company') or self.env.company.id"
@ormcache(COMPANY_KEY, 'name', 'model')
def _get_default_property(self, name, model):
prop = self._get_property(name, model, res_id=False)
if not prop:
return None, False
v = prop.get_by_record()
if prop.type != 'many2one':
return prop.type, v
return 'many2one', v and (v._name, v.id)
从以上代码中我们可以看出,对于新建的记录,因为没有资源值,因为会寻找ir.property对象中缺省的记录值来作为默认值。