Search code examples
multiple-inheritanceodoo-9

Embedded models storage in Odoo (Inherits)


I'm creating a custom module in odoo and I'm struggling with an inheritance issue, let's say i have the following implementation :

class SuperModel(models.Model) :
   _name="model_name"
   _inherits={'model_name.one':'model_name_one_id',
              'model_name.two':'model_name_two_id'}
   selection = fields.Selection(selection=[('m1','Model one'),('m2','Model Two')])
   model_name_one_id = fields.Many2one(comodel_name="model_name.one",ondelete="cascade")
   model_name_two_id = fields.Many2one(comodel_name="model_name.two",ondelete="cascade")

class ModelOne(models.Model):
   _name="model_name.one"
   value_one = fields.Char()

class ModelTwo(models.Model):
   _name="model_name.two"
   value_two = fields.Char()

What i want to achieve, is by selecting "Model 1" or "Model 2" in the main model view, only the corresponding fields will be displayed and stored in the database.

But whenever i create a record for "SuperModel" both records are created in "ModelOne" and "ModelTwo" tables.

For example if i select "Model 1" and fill "value_one", when saving, an empty record is created in "Model 2" table (model_name_two_id == False). How can i prevent that ?

Thank you for helping :)


Solution

  • OK using Delegate is impossible in you condition because odoo will make sure that the many2one must have a value or the saving will not happen so use related field like this

    class SuperModel(models.Model) :
       _name="model_name"
       selection = fields.Selection(selection=[('m1','Model one'),('m2','Model Two')])
       # indecate that the Many2one are delegated = true
       model_name_one_id = fields.Many2one(comodel_name="model_name.one",ondelete="cascade",  )
       model_name_two_id = fields.Many2one(comodel_name="model_name.two",ondelete="cascade", )
       value_one = fields.Char(related="model_name_one_id.value_one")
       value_two = fields.Char(related="model_name_two_id.value_two")
    
       @api.model
       def create(self, vals):
          if not rec_id.value_one:
            # if the related field of model_name_one_id are no null 
            # create  a record from that relateds fields add it to vals 
            # i used vals directly odoo is smart to ignore the non existing field in model_name.one 
            # or iterate the vals and extract a dictionary of model_name.one
            m2on_rec = self.env['model_name.one'].create(vals) # create a record 
            vals.update({'model_name_one_id':m2on_rec.id}) # add the id to vals
            return super(SuperModel, self).create(vals)
          elif not rec_id.value_one:
            # same thing for the second many2one 
          else :
               # show error or create a simple record
               return return super(SuperModel, self).create(vals) 
    
       @api.one # is used one so i make sure that self containing only one record it's hard for multi need to much code
       def write(self, vals):
                # check if any of the related field of model_name_one_id is changed
                if any(field_name in self.env['model_name.one'] for field_name in vals.keys()) :
                    # then check the many2one field all ready have a value so the operation here is update
                    if self.model_name_one_id:
                        return super(SuperModel, self).write(vals) # related field will do the changes
                    else :
                        # here we need to delete the record of model_name_two_id 
                        self.model_name_two_id.unlink()
                        # here the same thing in create you need to create the record
                        retrun super(SuperModel, self).write(vals) 
                else :
                     # same thing for model_name_two_id
    

    i tried this solution and it work sooo fine just create the record of the one2many field it's like you are the one who are delegating not the frame work for editing is more complex because you need to delete the record and then save the new one