【问题标题】:Odoo 10 - Get actual row or call function after savingOdoo 10 - 保存后获取实际行或调用函数
【发布时间】:2017-12-08 16:41:02
【问题描述】:

我正在处理表单内的表格。该表会自动填充用户必须执行的第一个字段的输入。在表格中只有一列用户必须输入数据,我让他们可以直接在表格中输入数据,而不是打开一个新表格。 这些数据需要使用隐藏在表格中的值进行检查,我只需要检查用户输入的值是否符合某些公差。

现在我的问题是,为了检查值,我需要知道值的 id 才能检查权限容差,但如果用户不保存表单,我将无法获取它们。

所以我有两个问题: 保存后是否可以调用函数?我知道我可以覆盖“创建”函数,但这不是我想要的,我希望在保存后立即调用一个函数,这要归功于我能够知道 ID 并且可以检查值。 如果那不可能,我的第二个问题是: 当用户输入它的值时,是否可以获得行号?使用 api.onchange 获取行号会很有用,因此我可以简单地循环到行中,直到找到正确的行,然后使用那里的数据。

感谢您的宝贵时间

EDIT1:这里是我用来循环数据的代码:

class ControlMeasure(models.Model):
    """
        Modèle pour la mesure d'une pièce
    """

# Nom de la table
_name = 'spc.control.measure' 

# Champs de la table
name                = fields.Many2one(string='Name', related='control_point_id.measure_type_id', readonly=True)
value               = fields.Float(string='Measured value')
validity            = fields.Boolean(string='Validity', readonly=True)
nominal_value       = fields.Float(string='Nominal value', related='control_point_id.nominal_value', readonly=True)

unit_id             = fields.Many2one('product.uom', string='Unit', related='control_point_id.product_uom_id', readonly=True)            
control_part_id     = fields.Many2one('spc.control.part', string='Controled piece')
control_point_id    = fields.Many2one('spc.control.point', string='Control point')

# Champs visuels
control_device_id   = fields.Many2one('spc.control.device', string='Used device', related='control_point_id.control_device_id')

# Vérifie si la valeur mesurée est dans la tolérance
@api.multi
@api.onchange('value')
def is_valid(self):   

   # raise Exception('Appel réussi')

    sql= """
            SELECT p.nominal_value, p.inferior_tolerance, p.superior_tolerance FROM spc_control_point p
            WHERE p.control_plan_id = %(ctrlid)s
         """

    if self.control_part_id.control_plan_id == False:
        raise Exception('False ' + str(self.control_part_id.control_plan_id))
    else:
        self.env.cr.execute(sql, {'ctrlid' : self.control_part_id.control_plan_id.id})
        row = self.env.cr.fetchall()

        for i in range(0, len(row)):
            #raise Exception(str(self.value) + ' < ' +  str(row[i][0]) + ' - ' +  str(abs(row[i][1])) +  ' or ' +  str(self.value) + ' > ' +  str(row[i][0]) + ' + ' +  str(abs(row[i][2])))
            if self.value < row[i][0] - abs(row[i][1]) or self.value > row[i][0] + abs(row[i][2]):
                self.validity = False 
            else:
                self.validity = True 

这里整个代码按我想要的方式工作,除了我不知道如何正确制作的循环,我检查了测试的数据是否正确,测试本身是否按我的意愿工作,但是正如您所看到的,每次我检查所有行和结尾时,只有最后一个才算数。 这就是为什么我提出了获取用户单击的行号的想法,但我不知道是否有可能做到这一点,甚至在保存后调用一个函数,这很容易,因为我知道 ID,我可以检查保存后的数据。

【问题讨论】:

    标签: odoo-10


    【解决方案1】:

    我想到了两种可能的解决方案:

    1. 正如您所提到的,您可以使用@api.onchange 装饰器创建一个方法,以在每次用户传入数据时检查输入的数据,而无需实际保存它或进行任何其他操作。

      @api.multi
      @api.onchange('your_field', 'your_field2')
      def _onchange_your_fields(self):
          for record in self:
              if record.your_field != record.validation_field:
                  raise exceptions.ValidationError(_('Sorry, pal, try again'))
      

    这样做的好处是,它将快速验证字段的值:在用户将光标放在下一个字段上之后。不过,从用户的角度来看,这可能会让人恼火。

    1. 你可以试试@api.constrains装饰器。它的行为与 @api.onchange 装饰器略有不同,但将其用于验证是一种常见做法。

      @api.multi
      @api.constrains('your_field', 'your_field2')
      def _check_your_fields(self):
          for record in self:
              if record.your_field != record.validation_field:
                  raise exceptions.ValidationError(_('Sorry, pal, try again'))
      

    不同之处在于它会在您点击“保存”按钮之后,但在实际执行createwrite 函数之前调用。

    希望,这会有所帮助。

    更新1:

    # Vérifie si la valeur mesurée est dans la tolérance
    @api.multi
    @api.onchange('value')
    def validate(self):
        # Because we are using @api.multi decorator, our 'self' is actually a recordset.
        # That means, that we cannot treat it as a regular record, so "self.control_part_id...." would be an odd code
        for record in self:
            # So now we took a one record from recordset, and now we can continue on validating it.
            if not record.control_part_id.control_plan_id:
                raise exceptions.UserError(_('False %s' % str(record.control_part_id.control_plan_id)))
    
            # You executed here a SQL query, which is actually takes our records from database, not from cache.
            # But we haven't write(or create) our changes yet, and that makes no sense.
    
            # What we wanna do, is to take values from cache and validate them. You can simply do it just via model's field
            validation_record = record.control_point_id
    
            if record.value < validation_row.nominal_value - validation_row.inferior_tolerance \
                or record.value > validation_row.nominal_value + validation_row.superior_tolerance:
                    record.validity = True
    
            else:
                # You can get rid of this line by simply defining the default value of record.validity as "False"
                record.validity = False
    
    
    # I recommend you to check the final validation this way
    @api.multi
    @api.constrains('validity')
    def check_valid(self):
        for record in self:
            if not record.validity:
                raise exceptions.ValidationError(_("Cannot pass a validation rest"))
    

    【讨论】:

    • 我实际上仍然有一个问题,也许我不太了解它是如何工作的,但是如果我采用您的第一个解决方案,我需要遍历多条记录,当我进行测试时我不要引发错误,但我将另一个字段设置为 false 或 true,如果它为 false,则整行变为红色,这就是我的问题所在。当我这样做时,只考虑最后一个值,我将编辑我的帖子以放置我为您制作的代码以了解我实际在做什么
    • 感谢您的帮助!我不知道我可以使用缓存来做到这一点!所以现在,它正确地进行了测试,但是当我保存时,有效性字段的值没有正确保存,当我在测试后显示该字段的值时它显示 True 但是当我保存它时默认为 False
    • 好的,我设法纠正了它!我犯了一个小错误。谢谢您的帮助 !我投票给你答案,但由于我的水平仍然很低,它没有显示它
    猜你喜欢
    • 1970-01-01
    • 2015-06-10
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多