Copy given record's data with all its fields values :param default: field values to override in the original values of the copied record :return: list of dictionaries containing all the field values
(self, default: ValuesType | None = None)
| 5404 | return query |
| 5405 | |
| 5406 | def copy_data(self, default: ValuesType | None = None) -> list[ValuesType]: |
| 5407 | """ |
| 5408 | Copy given record's data with all its fields values |
| 5409 | |
| 5410 | :param default: field values to override in the original values of the copied record |
| 5411 | :return: list of dictionaries containing all the field values |
| 5412 | """ |
| 5413 | vals_list = [] |
| 5414 | default = dict(default or {}) |
| 5415 | # avoid recursion through already copied records in case of circular relationship |
| 5416 | if '__copy_data_seen' not in self.env.context: |
| 5417 | self = self.with_context(__copy_data_seen=defaultdict(set)) |
| 5418 | |
| 5419 | # build a black list of fields that should not be copied |
| 5420 | blacklist = set(MAGIC_COLUMNS + ['parent_path']) |
| 5421 | whitelist = set(name for name, field in self._fields.items() if not field.inherited) |
| 5422 | |
| 5423 | def blacklist_given_fields(model): |
| 5424 | # blacklist the fields that are given by inheritance |
| 5425 | for parent_model, parent_field in model._inherits.items(): |
| 5426 | blacklist.add(parent_field) |
| 5427 | if parent_field in default: |
| 5428 | # all the fields of 'parent_model' are given by the record: |
| 5429 | # default[parent_field], except the ones redefined in self |
| 5430 | blacklist.update(set(self.env[parent_model]._fields) - whitelist) |
| 5431 | else: |
| 5432 | blacklist_given_fields(self.env[parent_model]) |
| 5433 | |
| 5434 | blacklist_given_fields(self) |
| 5435 | |
| 5436 | fields_to_copy = {name: field |
| 5437 | for name, field in self._fields.items() |
| 5438 | if field.copy and name not in default and name not in blacklist} |
| 5439 | |
| 5440 | for record in self: |
| 5441 | seen_map = self.env.context['__copy_data_seen'] |
| 5442 | if record.id in seen_map[record._name]: |
| 5443 | vals_list.append(None) |
| 5444 | continue |
| 5445 | seen_map[record._name].add(record.id) |
| 5446 | |
| 5447 | vals = default.copy() |
| 5448 | |
| 5449 | for name, field in fields_to_copy.items(): |
| 5450 | if field.type == 'one2many': |
| 5451 | # duplicate following the order of the ids because we'll rely on |
| 5452 | # it later for copying translations in copy_translation()! |
| 5453 | lines = record[name].sorted(key='id').copy_data() |
| 5454 | # the lines are duplicated using the wrong (old) parent, but then are |
| 5455 | # reassigned to the correct one thanks to the (Command.CREATE, 0, ...) |
| 5456 | vals[name] = [Command.create(line) for line in lines if line] |
| 5457 | elif field.type == 'many2many': |
| 5458 | # copy only links that we can read, otherwise the write will fail |
| 5459 | vals[name] = [Command.set(record[name]._filtered_access('read').ids)] |
| 5460 | else: |
| 5461 | vals[name] = field.convert_to_write(record[name], record) |
| 5462 | vals_list.append(vals) |
| 5463 | return vals_list |
no test coverage detected