Create 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 vals_list: values for the model's fields, as a list of dictionaries::
(self, vals_list: list[ValuesType])
| 4609 | |
| 4610 | @api.model_create_multi |
| 4611 | def create(self, vals_list: list[ValuesType]) -> Self: |
| 4612 | """Create new records for the model. |
| 4613 | |
| 4614 | The new records are initialized using the values from the list of dicts |
| 4615 | ``vals_list``, and if necessary those from :meth:`~.default_get`. |
| 4616 | |
| 4617 | :param vals_list: |
| 4618 | values for the model's fields, as a list of dictionaries:: |
| 4619 | |
| 4620 | [{'field_name': field_value, ...}, ...] |
| 4621 | |
| 4622 | For backward compatibility, ``vals_list`` may be a dictionary. |
| 4623 | It is treated as a singleton list ``[vals]``, and a single record |
| 4624 | is returned. |
| 4625 | |
| 4626 | see :meth:`~.write` for details |
| 4627 | |
| 4628 | :return: the created records |
| 4629 | :raise AccessError: if the current user is not allowed to create records of the specified model |
| 4630 | :raise ValidationError: if user tries to enter invalid value for a selection field |
| 4631 | :raise ValueError: if a field name specified in the create values does not exist. |
| 4632 | :raise UserError: if a loop would be created in a hierarchy of objects a result of the operation |
| 4633 | (such as setting an object as its own parent) |
| 4634 | """ |
| 4635 | assert isinstance(vals_list, (list, tuple)) |
| 4636 | if not vals_list: |
| 4637 | return self.browse() |
| 4638 | |
| 4639 | self = self.browse() |
| 4640 | self.check_access('create') |
| 4641 | |
| 4642 | # check access to all user-provided fields |
| 4643 | field_names = OrderedSet(fname for vals in vals_list for fname in vals) |
| 4644 | field_names.update( |
| 4645 | field_name |
| 4646 | for context_key in self.env.context |
| 4647 | if context_key.startswith('default_') |
| 4648 | and (field_name := context_key[8:]) |
| 4649 | and field_name in self._fields |
| 4650 | ) |
| 4651 | for field_name in field_names: |
| 4652 | field = self._fields.get(field_name) |
| 4653 | if field is None: |
| 4654 | raise ValueError(f"Invalid field {field_name!r} in {self._name!r}") |
| 4655 | self._check_field_access(field, 'write') |
| 4656 | |
| 4657 | new_vals_list = self._prepare_create_values(vals_list) |
| 4658 | |
| 4659 | # classify fields for each record |
| 4660 | data_list = [] |
| 4661 | determine_inverses = defaultdict(OrderedSet) # {inverse: fields} |
| 4662 | |
| 4663 | for vals in new_vals_list: |
| 4664 | precomputed = vals.pop('__precomputed__', ()) |
| 4665 | |
| 4666 | # distribute fields into sets for various purposes |
| 4667 | data = {} |
| 4668 | data['stored'] = stored = {} |
no test coverage detected