简体   繁体   English

如何在Odoo 8中创建或写入时标准化字段值?

[英]How to standardize field values on create or write in Odoo 8?

In Odoo 8, is there a preferred method for standardizing field values on create or write? 在Odoo 8中,是否有一种在创建或写入时标准化字段值的首选方法? Several methods come to mind, but this functionality seems like it belongs in the API. 我想到了几种方法,但这个功能似乎属于API。 Essentially, I am wanting to create a field that specifies a standardize function, somewhat like a compute field that only specifies an inverse function. 本质上,我想创建一个指定标准化函数的字段,有点像只指定反函数的计算字段。 Does this already exist somewhere in the API? 这是否已经存在于API中的某个位置?

Method 0: Create a field that specifies a standardize function. 方法0:创建一个指定标准化函数的字段。

The only flaw that I can see with this method is that the API does not exist. 我能用这种方法看到的唯一缺陷是API不存在。

import openerp

class Model(openerp.models.Model):

  _name = 'addon.model'

  field = openerp.fields.Text(
    required=True,
    standardize='_standardize_field',
  )

  @openerp.api.one
  def _standardize_field(self):
    self.field = self.field.upper()

Method 1: Override the create and write methods to insert a call to standardize the field. 方法1:覆盖create和write方法以插入调用以标准化字段。

This works, but seems rather verbose for what could be done with a single function, above. 这可行,但对于上面的单个函数可以做什么似乎相当冗长。 Note that the constraint is required if required=True and the standardization might yield an empty field. 请注意,如果required=True且标准化可能产生空字段,则required=True约束。

import openerp

class Model(openerp.models.Model):

  _name = 'addon.model'

  field = openerp.fields.Text(
    required=True,
  )

  @openerp.api.one
  @openerp.api.constrains('field')
  def _constrains_field(self):
    if len(self.field) == 0:
      raise openerp.exceptions.ValidationError('Field must be valid.')

  def _standardize(self, args):
    if 'field' in args:
      # Return standardized field or empty string.
      args['field'] = args['field'].upper()

  @openerp.api.model
  def create(self, args):
    self._standardize(args)
    return super(Model, self).create(args)

  @openerp.api.multi
  def write(self, args):
    self._standardize(args)
    super(Model, self).write(args)
    return True

Method 2: Use a computed field and a bit of magic. 方法2:使用计算字段和一点魔法。

This works but feels a bit contrived. 这有效,但感觉有点做作。 In addition, this method requires that the standardization function is deterministic, or this may create an infinite loop. 此外,此方法要求标准化函数是确定性的,否则可能会产生无限循环。 Note that the standardization function may be called twice, which could be a concern if standardization is an expensive operation. 请注意,标准化功能可能会被调用两次,如果标准化是一项昂贵的操作,这可能是一个问题。

import openerp

class Model(openerp.models.Model):

  _name = 'addon.model'

  field = openerp.fields.Text(
    compute=lambda x: x,
    inverse='_inverse_field',
    required=True,
    store=True,
  )

  @openerp.api.one
  @openerp.api.constrains('field')
  def _constrains_field(self):
    if self._standardize_field() is None:
      raise openerp.exceptions.ValidationError('Field must be valid.')

  def _inverse_field(self):
    field = self._standardize_field()

    # If the field is updated during standardization, this function will
    # run a second time, so use this check to prevent an infinite loop.
    if self.field != field:
      self.field = field

  def _standardize_field(self):
    # Return the standardized field.
    return self.field.upper()

Method 3: Use a regular field and a computed field, with only the computed field being exposed in the view. 方法3:使用常规字段和计算字段,仅在视图中公开计算字段。

The readonly flag and the constraints help to protect the underlying field, but I am not certain that this method would maintain data integrity, and the method as a whole feels contrived. readonly标志和约束有助于保护底层字段,但我不确定这种方法是否会保持数据完整性,并且整个方法感觉很人为。

import openerp

class Model(openerp.models.Model):

  _name = 'addon.model'

  field = openerp.fields.Text(
    readonly=True,
    required=True,
  )

  field_for_view = openerp.fields.Text(
    compute='_compute_field_for_view',
    inverse='_inverse_field_for_view',
    required=True,
  )

  @openerp.api.one
  @openerp.api.depends('field')
  def _compute_field_for_view(self):
    self.field_for_view = self.field

  @openerp.api.one
  @openerp.api.constrains('field', 'field_for_view')
  def _constrains_field(self):
    if self._standardize_field() is None:
      raise openerp.exceptions.ValidationError('Field must be valid.')

  def _inverse_field(self):
    self.field = self._standardize_field()

  def _standardize_field(self):
    # Return the standardized field.
    return self.field_for_view.upper()

Maybe the 'default' attribute is an implementation of your approach #1? 也许“默认”属性是您的方法#1的实现? Here's the example taken from the Odoo8 documentation at https://www.odoo.com/documentation/8.0/reference/orm.html#creating-models 以下是来自https://www.odoo.com/documentation/8.0/reference/orm.html#creating-models上的Odoo8文档的示例

a_field = fields.Char(default=compute_default_value)

def compute_default_value(self):
    return self.get_value()

Another option is to override the write() method in your subclass to add your call like so: 另一种选择是覆盖子类中的write()方法来添加你的调用,如下所示:

    def write(self, vals):

        for record in self:
            # do the cleanup here for each record, storing the result in 
            # vals again

        # call the super:
        res = super(extendedProject, self).write(vals)

        return res

vals is a dictionary with the modified values to store; vals是一个包含要存储的修改值的字典; self is a recordset with all records to store the values to. self是一个记录集,包含存储值的所有记录。 Note that the transaction in Odoo may still be rolled back after returning from your call to write . 请注意,从调用write返回后,Odoo中的事务仍可能会回滚。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM