(self, vals_list)
return records
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)
create(vals_list) -> records
create ( vals_list ) - > records
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
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