[IMP] core: import-compatible export of m2m fields
When performing an import-compatible export, m2m values would be exported as a record per cell unless the `id` subfield was the first to be exported. Which is not the case when using the export UI (as it always adds the field itself before any subfield). This would make the m2m not actually export-compatible in most cases. * export m2m "display name" in an import compatible format as well * re-prioritise exporting xids when there are multiple m2m exports in import-compatible mode * never fall back on the o2m / non-import-compatible m2m path for m2ms in import-compatible mode Note: if multiple m2m fields are specified only one of them gets filled. Task 2065428 closes odoo/odoo#37407 Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com> Co-authored-by: Ravi Singh <ras@odoo.com> Co-authored-by: Mohammed Shekha <msh@odoo.com> Co-authored-by: Xavier Morel <xmo@odoo.com>
This commit is contained in:
committed by
Xavier Morel
co-authored by
Mohammed Shekha
Xavier Morel
parent
3ecea2c934
commit
574d7f0d4c
@@ -606,18 +606,20 @@ class test_m2m(CreatorCase):
|
||||
def test_single_subfield(self):
|
||||
self.assertEqual(
|
||||
self.export([(0, False, {'value': 42})],
|
||||
fields=['value', 'value/value']),
|
||||
fields=['value', 'value/value'],
|
||||
context={'import_compat': False}),
|
||||
[[u'export.many2many.other:42', 42]])
|
||||
|
||||
def test_integrate_one_in_parent(self):
|
||||
self.assertEqual(
|
||||
self.export([(0, False, {'value': 42})],
|
||||
fields=['const', 'value/value']),
|
||||
fields=['const', 'value/value'],
|
||||
context={'import_compat': False}),
|
||||
[[4, 42]])
|
||||
|
||||
def test_multiple_records(self):
|
||||
self.assertEqual(
|
||||
self.export(self.commands, fields=['const', 'value/value']),
|
||||
self.export(self.commands, fields=['const', 'value/value'], context={'import_compat': False}),
|
||||
[
|
||||
[4, 4],
|
||||
[u'', 42],
|
||||
@@ -629,6 +631,12 @@ class test_m2m(CreatorCase):
|
||||
def test_multiple_records_name(self):
|
||||
self.assertEqual(
|
||||
self.export(self.commands, fields=['const', 'value']),
|
||||
[
|
||||
[4, 'export.many2many.other:4,export.many2many.other:42,export.many2many.other:36,export.many2many.other:4,export.many2many.other:13'],
|
||||
])
|
||||
|
||||
self.assertEqual(
|
||||
self.export(self.commands, fields=['const', 'value'], context={'import_compat': False}),
|
||||
[
|
||||
[4, u'export.many2many.other:4'],
|
||||
['', u'export.many2many.other:42'],
|
||||
@@ -664,6 +672,10 @@ class test_m2m(CreatorCase):
|
||||
r.with_context(import_compat=True)._export_rows([['value', 'id']]),
|
||||
[['__t__.record000,__t__.record001,__t__.record010,__t__.record011,__t__.record100']]
|
||||
)
|
||||
self.assertEqual(
|
||||
r.with_context(import_compat=True)._export_rows([['value'], ['value', 'id']]),
|
||||
[['', '__t__.record000,__t__.record001,__t__.record010,__t__.record011,__t__.record100']]
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
r.with_context(import_compat=False)._export_rows([['id'], ['value', 'id'], ['value', 'value']]),
|
||||
|
||||
+26
-8
@@ -22,6 +22,7 @@
|
||||
"""
|
||||
|
||||
import collections
|
||||
import contextlib
|
||||
import datetime
|
||||
import dateutil
|
||||
import fnmatch
|
||||
@@ -838,18 +839,35 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
|
||||
current[i] = field.convert_to_export(value, record)
|
||||
else:
|
||||
primary_done.append(name)
|
||||
|
||||
# in import_compat mode, m2m should always be exported as
|
||||
# a comma-separated list of xids in a single cell
|
||||
if import_compatible and field.type == 'many2many' and len(path) > 1 and path[1] == 'id':
|
||||
xml_ids = [xid for _, xid in value.__ensure_xml_id()]
|
||||
current[i] = ','.join(xml_ids) or False
|
||||
continue
|
||||
|
||||
# recursively export the fields that follow name; use
|
||||
# 'display_name' where no subfield is exported
|
||||
fields2 = [(p[1:] or ['display_name'] if p and p[0] == name else [])
|
||||
for p in fields]
|
||||
|
||||
# in import_compat mode, m2m should always be exported as
|
||||
# a comma-separated list of xids or names in a single cell
|
||||
if import_compatible and field.type == 'many2many':
|
||||
index = None
|
||||
# find out which subfield the user wants & its
|
||||
# location as we might not get it as the first
|
||||
# column we encounter
|
||||
for name in ['id', 'name', 'display_name']:
|
||||
with contextlib.suppress(ValueError):
|
||||
index = fields2.index([name])
|
||||
break
|
||||
if index is None:
|
||||
# not found anything, assume we just want the
|
||||
# name_get in the first column
|
||||
name = None
|
||||
index = i
|
||||
|
||||
if name == 'id':
|
||||
xml_ids = [xid for _, xid in value.__ensure_xml_id()]
|
||||
current[index] = ','.join(xml_ids) or False
|
||||
else:
|
||||
current[index] = field.convert_to_export(value, record) or False
|
||||
continue
|
||||
|
||||
lines2 = value._export_rows(fields2, _is_toplevel_call=False)
|
||||
if lines2:
|
||||
# merge first line with record's main line
|
||||
|
||||
Reference in New Issue
Block a user