Nero Ouali
Nero Ouali

Reputation: 208

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 :)

Upvotes: 0

Views: 416

Answers (1)

Charif DZ
Charif DZ

Reputation: 14731

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

Upvotes: 1

Related Questions