parameters: (self, vals_list)
return_statement: return records
docstring: create(vals_list) -> records
  
          Creates new records for the model.
  
          The new records are initialized using the values from the list of dicts
          ``vals_list``, and if necessary those from :meth:`~.default_get`.
  
          :param list vals_list:
              values for the model's fields, as a list of dictionaries::
  
                  [{'field_name': field_value, ...}, ...]
  
              For backward compatibility, ``vals_list`` may be a dictionary.
              It is treated as a singleton list ``[vals]``, and a single record
              is returned.
  
              see :meth:`~.write` for details
  
          :return: the created records
          :raise AccessError: * if user has no create rights on the requested object
                              * if user tries to bypass access rules for create on the requested object
          :raise ValidationError: if user tries to enter invalid value for a field that is not in selection
          :raise UserError: if a loop would be created in a hierarchy of objects a result of the operation (such as setting an object as its own parent)
docstring_summary: create(vals_list) -> records
docstring_tokens: create ( vals_list ) - > records
function: def create(self, vals_list):
          """ create(vals_list) -> records
  
          Creates new records for the model.
  
          The new records are initialized using the values from the list of dicts
          ``vals_list``, and if necessary those from :meth:`~.default_get`.
  
          :param list vals_list:
              values for the model's fields, as a list of dictionaries::
  
                  [{'field_name': field_value, ...}, ...]
  
              For backward compatibility, ``vals_list`` may be a dictionary.
              It is treated as a singleton list ``[vals]``, and a single record
              is returned.
  
              see :meth:`~.write` for details
  
          :return: the created records
          :raise AccessError: * if user has no create rights on the requested object
                              * if user tries to bypass access rules for create on the requested object
          :raise ValidationError: if user tries to enter invalid value for a field that is not in selection
          :raise UserError: if a loop would be created in a hierarchy of objects a result of the operation (such as setting an object as its own parent)
          """
          if not vals_list:
              return self.browse()
  
          self = self.browse()
          self.check_access_rights('create')
  
          bad_names = {'id', 'parent_path'}
          if self._log_access:
              # the superuser can set log_access fields while loading registry
              if not(self.env.uid == SUPERUSER_ID and not self.pool.ready):
                  bad_names.update(LOG_ACCESS_COLUMNS)
  
          # classify fields for each record
          data_list = []
          inversed_fields = set()
  
          for vals in vals_list:
              # add missing defaults
              vals = self._add_missing_default_values(vals)
  
              # set magic fields
              for name in bad_names:
                  vals.pop(name, None)
              if self._log_access:
                  vals.setdefault('create_uid', self.env.uid)
                  vals.setdefault('create_date', self.env.cr.now())
                  vals.setdefault('write_uid', self.env.uid)
                  vals.setdefault('write_date', self.env.cr.now())
  
              # distribute fields into sets for various purposes
              data = {}
              data['stored'] = stored = {}
              data['inversed'] = inversed = {}
              data['inherited'] = inherited = defaultdict(dict)
              data['protected'] = protected = set()
              for key, val in vals.items():
                  field = self._fields.get(key)
                  if not field:
                      raise ValueError("Invalid field %r on model %r" % (key, self._name))
                  if field.company_dependent:
                      irprop_def = self.env['ir.property']._get(key, self._name)
                      cached_def = field.convert_to_cache(irprop_def, self)
                      cached_val = field.convert_to_cache(val, self)
                      if cached_val == cached_def:
                          # val is the same as the default value defined in
                          # 'ir.property'; by design, 'ir.property' will not
                          # create entries specific to these records; skipping the
                          # field inverse saves 4 SQL queries
                          continue
                  if field.store:
                      stored[key] = val
                  if field.inherited:
                      inherited[field.related_field.model_name][key] = val
                  elif field.inverse:
                      inversed[key] = val
                      inversed_fields.add(field)
                  # protect non-readonly computed fields against (re)computation
                  if field.compute and not field.readonly:
                      protected.update(self.pool.field_computed.get(field, [field]))
  
              data_list.append(data)
  
          # create or update parent records
          for model_name, parent_name in self._inherits.items():
              parent_data_list = []
              for data in data_list:
                  if not data['stored'].get(parent_name):
                      parent_data_list.append(data)
                  elif data['inherited'][model_name]:
                      parent = self.env[model_name].browse(data['stored'][parent_name])
                      parent.write(data['inherited'][model_name])
  
              if parent_data_list:
                  parents = self.env[model_name].create([
                      data['inherited'][model_name]
                      for data in parent_data_list
                  ])
                  for parent, data in zip(parents, parent_data_list):
                      data['stored'][parent_name] = parent.id
  
          # create records with stored fields
          records = self._create(data_list)
  
          # protect fields being written against recomputation
          protected = [(data['protected'], data['record']) for data in data_list]
          with self.env.protecting(protected):
              # group fields by inverse method (to call it once), and order groups
              # by dependence (in case they depend on each other)
              field_groups = (fields for _inv, fields in groupby(inversed_fields, attrgetter('inverse')))
              for fields in field_groups:
                  # determine which records to inverse for those fields
                  inv_names = {field.name for field in fields}
                  rec_vals = [
                      (data['record'], {
                          name: data['inversed'][name]
                          for name in inv_names
                          if name in data['inversed']
                      })
                      for data in data_list
                      if not inv_names.isdisjoint(data['inversed'])
                  ]
  
                  # If a field is not stored, its inverse method will probably
                  # write on its dependencies, which will invalidate the field on
                  # all records. We therefore inverse the field record by record.
                  if all(field.store or field.company_dependent for field in fields):
                      batches = [rec_vals]
                  else:
                      batches = [[rec_data] for rec_data in rec_vals]
  
                  for batch in batches:
                      for record, vals in batch:
                          record._update_cache(vals)
                      batch_recs = self.concat(*(record for record, vals in batch))
                      fields[0].determine_inverse(batch_recs)
  
          # check Python constraints for non-stored inversed fields
          for data in data_list:
              data['record']._validate_fields(data['inversed'], data['stored'])
  
          if self._check_company_auto:
              records._check_company()
          return records
function_tokens: def create ( self , vals_list ) : if not vals_list : return self . browse ( ) self = self . browse ( ) self . check_access_rights ( 'create' ) bad_names = { 'id' , 'parent_path' } if self . _log_access : # the superuser can set log_access fields while loading registry if not ( self . env . uid == SUPERUSER_ID and not self . pool . ready ) : bad_names . update ( LOG_ACCESS_COLUMNS ) # classify fields for each record data_list = [ ] inversed_fields = set ( ) for vals in vals_list : # add missing defaults vals = self . _add_missing_default_values ( vals ) # set magic fields for name in bad_names : vals . pop ( name , None ) if self . _log_access : vals . setdefault ( 'create_uid' , self . env . uid ) vals . setdefault ( 'create_date' , self . env . cr . now ( ) ) vals . setdefault ( 'write_uid' , self . env . uid ) vals . setdefault ( 'write_date' , self . env . cr . now ( ) ) # distribute fields into sets for various purposes data = { } data [ 'stored' ] = stored = { } data [ 'inversed' ] = inversed = { } data [ 'inherited' ] = inherited = defaultdict ( dict ) data [ 'protected' ] = protected = set ( ) for key , val in vals . items ( ) : field = self . _fields . get ( key ) if not field : raise ValueError ( "Invalid field %r on model %r" % ( key , self . _name ) ) if field . company_dependent : irprop_def = self . env [ 'ir.property' ] . _get ( key , self . _name ) cached_def = field . convert_to_cache ( irprop_def , self ) cached_val = field . convert_to_cache ( val , self ) if cached_val == cached_def : # val is the same as the default value defined in # 'ir.property'; by design, 'ir.property' will not # create entries specific to these records; skipping the # field inverse saves 4 SQL queries continue if field . store : stored [ key ] = val if field . inherited : inherited [ field . related_field . model_name ] [ key ] = val elif field . inverse : inversed [ key ] = val inversed_fields . add ( field ) # protect non-readonly computed fields against (re)computation if field . compute and not field . readonly : protected . update ( self . pool . field_computed . get ( field , [ field ] ) ) data_list . append ( data ) # create or update parent records for model_name , parent_name in self . _inherits . items ( ) : parent_data_list = [ ] for data in data_list : if not data [ 'stored' ] . get ( parent_name ) : parent_data_list . append ( data ) elif data [ 'inherited' ] [ model_name ] : parent = self . env [ model_name ] . browse ( data [ 'stored' ] [ parent_name ] ) parent . write ( data [ 'inherited' ] [ model_name ] ) if parent_data_list : parents = self . env [ model_name ] . create ( [ data [ 'inherited' ] [ model_name ] for data in parent_data_list ] ) for parent , data in zip ( parents , parent_data_list ) : data [ 'stored' ] [ parent_name ] = parent . id # create records with stored fields records = self . _create ( data_list ) # protect fields being written against recomputation protected = [ ( data [ 'protected' ] , data [ 'record' ] ) for data in data_list ] with self . env . protecting ( protected ) : # group fields by inverse method (to call it once), and order groups # by dependence (in case they depend on each other) field_groups = ( fields for _inv , fields in groupby ( inversed_fields , attrgetter ( 'inverse' ) ) ) for fields in field_groups : # determine which records to inverse for those fields inv_names = { field . name for field in fields } rec_vals = [ ( data [ 'record' ] , { name : data [ 'inversed' ] [ name ] for name in inv_names if name in data [ 'inversed' ] } ) for data in data_list if not inv_names . isdisjoint ( data [ 'inversed' ] ) ] # If a field is not stored, its inverse method will probably # write on its dependencies, which will invalidate the field on # all records. We therefore inverse the field record by record. if all ( field . store or field . company_dependent for field in fields ) : batches = [ rec_vals ] else : batches = [ [ rec_data ] for rec_data in rec_vals ] for batch in batches : for record , vals in batch : record . _update_cache ( vals ) batch_recs = self . concat ( * ( record for record , vals in batch ) ) fields [ 0 ] . determine_inverse ( batch_recs ) # check Python constraints for non-stored inversed fields for data in data_list : data [ 'record' ] . _validate_fields ( data [ 'inversed' ] , data [ 'stored' ] ) if self . _check_company_auto : records . _check_company ( ) return records