Allow to use Reference field in One2Many & Many2Many

review378002
This commit is contained in:
Cédric Krier
2012-06-08 19:27:19 +02:00
parent e4dd1a25d0
commit 1aae951f92
7 changed files with 649 additions and 119 deletions
+1
View File
@@ -1,3 +1,4 @@
* Allow to use Reference field in One2Many & Many2Many
* Remove hexmd5 from ModelView.fields_view_get
* Allow client to manage model access
* Add time format validation
+6 -3
View File
@@ -418,7 +418,8 @@ One2Many
.. class:: One2Many(model_name, field, string[, add_remove[, order[, datetime_field[, \**options]]]])
A one-to-many relation field. It requires to have the opposite
:class:`Many2One` field defined on the target model.
:class:`Many2One` field or a :class:`Reference` field defined on the target
model.
This field accepts as written value a list of tuples like this:
@@ -449,7 +450,8 @@ This field accepts as written value a list of tuples like this:
.. attribute:: One2Many.field
The name of the field that handles the opposite :class:`Many2One`
The name of the field that handles the opposite :class:`Many2One` or
:class:`Reference`.
:class:`One2Many` has some extra optional arguments:
@@ -483,7 +485,8 @@ A many-to-many relation field.
.. attribute:: Many2Many.origin
The name of the field that has the :class:`Many2One` to the record.
The name of the field that has the :class:`Many2One` or :class:`Reference`
to the record.
.. attribute:: Many2Many.target
+66 -27
View File
@@ -68,18 +68,30 @@ class Many2Many(Field):
order = self.order
relation_obj = Pool().get(self.relation_name)
if self.origin in relation_obj._columns:
origin_field = relation_obj._columns[self.origin]
else:
origin_field = relation_obj._inherit_fields[self.origin][2]
relation_ids = []
for i in range(0, len(ids), Transaction().cursor.IN_MAX):
sub_ids = ids[i:i + Transaction().cursor.IN_MAX]
relation_ids.append(relation_obj.search([
(self.origin, 'in', sub_ids),
(self.target + '.id', '!=', False),
], order=order))
if origin_field._type == 'reference':
references = ['%s,%s' % (model._name, x) for x in sub_ids]
clause = [(self.origin, 'in', references)]
else:
clause = [(self.origin, 'in', sub_ids)]
clause += [(self.target + '.id', '!=', None)]
relation_ids.append(relation_obj.search(clause, order=order))
relation_ids = list(chain(*relation_ids))
for relation in relation_obj.browse(relation_ids):
res[relation[self.origin].id].append(relation[self.target].id)
if origin_field._type == 'reference':
_, origin_id = relation[self.origin].split(',')
origin_id = int(origin_id)
else:
origin_id = relation[self.origin].id
res[origin_id].append(relation[self.target].id)
return res
def set(self, ids, model, name, values):
@@ -93,26 +105,53 @@ class Many2Many(Field):
(``create``, ``{<field name>: value}``),
(``write``, ``<ids>``, ``{<field name>: value}``),
(``delete``, ``<ids>``),
(``delete_all``),
(``unlink``, ``<ids>``),
(``add``, ``<ids>``),
(``unlink_all``),
(``set``, ``<ids>``)
'''
pool = Pool()
if not values:
return
relation_obj = Pool().get(self.relation_name)
relation_obj = pool.get(self.relation_name)
target_obj = self.get_target()
if self.origin in relation_obj._columns:
origin_field = relation_obj._columns[self.origin]
else:
origin_field = relation_obj._inherit_fields[self.origin][2]
def search_clause(ids):
if origin_field._type == 'reference':
references = ['%s,%s' % (model._name, x) for x in ids]
return (self.origin, 'in', references)
else:
return (self.origin, 'in', ids)
def field_value(record_id):
if origin_field._type == 'reference':
return '%s,%s' % (model._name, record_id)
else:
return record_id
for act in values:
if act[0] == 'create':
for record_id in ids:
relation_obj.create({
self.origin: record_id,
self.target: target_obj.create(act[1]),
})
self.origin: field_value(record_id),
self.target: target_obj.create(act[1]),
})
elif act[0] == 'write':
target_obj.write(act[1], act[2])
elif act[0] == 'delete':
target_obj.delete(act[1])
elif act[0] == 'delete_all':
relations = relation_obj.browse(relation_obj.search([
search_clause(ids),
]))
target_obj.delete([r[self.target].id for r in relations
if r[self.target].id])
elif act[0] == 'unlink':
if isinstance(act[1], (int, long)):
target_ids = [act[1]]
@@ -125,9 +164,9 @@ class Many2Many(Field):
Transaction().cursor.IN_MAX):
sub_ids = target_ids[i:i + Transaction().cursor.IN_MAX]
relation_ids += relation_obj.search([
(self.origin, 'in', ids),
(self.target, 'in', sub_ids),
])
search_clause(ids),
(self.target, 'in', sub_ids),
])
relation_obj.delete(relation_ids)
elif act[0] == 'add':
if isinstance(act[1], (int, long)):
@@ -141,22 +180,22 @@ class Many2Many(Field):
Transaction().cursor.IN_MAX):
sub_ids = target_ids[i:i + Transaction().cursor.IN_MAX]
relation_ids = relation_obj.search([
(self.origin, 'in', ids),
(self.target, 'in', sub_ids),
])
search_clause(ids),
(self.target, 'in', sub_ids),
])
for relation in relation_obj.browse(relation_ids):
existing_ids.append(relation[self.target].id)
for new_id in (x for x in target_ids if x not in existing_ids):
for record_id in ids:
relation_obj.create({
self.origin: record_id,
self.target: new_id,
})
self.origin: field_value(record_id),
self.target: new_id,
})
elif act[0] == 'unlink_all':
target_ids = relation_obj.search([
(self.origin, 'in', ids),
(self.target + '.id', '!=', False),
])
search_clause(ids),
(self.target + '.id', '!=', None),
])
relation_obj.delete(target_ids)
elif act[0] == 'set':
if not act[1]:
@@ -164,17 +203,17 @@ class Many2Many(Field):
else:
target_ids = list(act[1])
target_ids2 = relation_obj.search([
(self.origin, 'in', ids),
(self.target + '.id', '!=', False),
])
search_clause(ids),
(self.target + '.id', '!=', None),
])
relation_obj.delete(target_ids2)
for new_id in target_ids:
for record_id in ids:
relation_obj.create({
self.origin: record_id,
self.target: new_id,
})
self.origin: field_value(record_id),
self.target: new_id,
})
else:
raise Exception('Bad arguments')
+74 -43
View File
@@ -24,7 +24,8 @@ class One2Many(Field):
loading='lazy'):
'''
:param model_name: The name of the target model.
:param field: The name of the field that handle the reverse many2one.
:param field: The name of the field that handle the reverse many2one or
reference.
:param add_remove: A list that defines a domain on add/remove.
See domain on ModelStorage.search.
:param order: a list of tuples that are constructed like this:
@@ -66,21 +67,29 @@ class One2Many(Field):
Return target records ordered.
:param ids: a list of ids
:param model: a string with the name of the model
:param model: the model
:param name: a string with the name of the field
:param values: a dictionary with the read values
:return: a dictionary with ids as key and values as value
'''
pool = Pool()
relation_obj = pool.get(self.model_name)
if self.field in relation_obj._columns:
field = relation_obj._columns[self.field]
else:
field = relation_obj._inherit_fields[self.field][2]
res = {}
for i in ids:
res[i] = []
ids2 = []
for i in range(0, len(ids), Transaction().cursor.IN_MAX):
sub_ids = ids[i:i + Transaction().cursor.IN_MAX]
ids2.append(pool.get(self.model_name).search([
(self.field, 'in', sub_ids),
], order=self.order))
if field._type == 'reference':
references = ['%s,%s' % (model._name, x) for x in sub_ids]
clause = [(self.field, 'in', references)]
else:
clause = [(self.field, 'in', sub_ids)]
ids2.append(relation_obj.search(clause, order=self.order))
cache = Transaction().cursor.get_cache(Transaction().context)
cache.setdefault(self.model_name, {})
@@ -93,8 +102,13 @@ class One2Many(Field):
ids3.append(i)
if ids3:
for i in pool.get(self.model_name).read(ids3, [self.field]):
res[i[self.field]].append(i['id'])
for i in relation_obj.read(ids3, [self.field]):
if field._type == 'reference':
_, id_ = i[self.field].split(',')
id_ = int(id_)
else:
id_ = i[self.field]
res[id_].append(i['id'])
index_of_ids2 = dict((i, index)
for index, i in enumerate(chain(*ids2)))
@@ -107,7 +121,7 @@ class One2Many(Field):
Set the values.
:param ids: A list of ids
:param model: A string with the name of the model
:param model: the model
:param name: A string with the name of the field
:param values: A list of tuples:
(``create``, ``{<field name>: value}``),
@@ -122,21 +136,38 @@ class One2Many(Field):
pool = Pool()
if not values:
return
model = pool.get(self.model_name)
target_obj = pool.get(self.model_name)
if self.field in target_obj._columns:
field = target_obj._columns[self.field]
else:
field = target_obj._inherit_fields[self.field][2]
def search_clause(ids):
if field._type == 'reference':
references = ['%s,%s' % (model._name, x) for x in ids]
return (self.field, 'in', references)
else:
return (self.field, 'in', ids)
def field_value(record_id):
if field._type == 'reference':
return '%s,%s' % (model._name, record_id)
else:
return record_id
for act in values:
if act[0] == 'create':
for record_id in ids:
act[1][self.field] = record_id
model.create(act[1])
act[1][self.field] = field_value(record_id)
target_obj.create(act[1])
elif act[0] == 'write':
model.write(act[1], act[2])
target_obj.write(act[1], act[2])
elif act[0] == 'delete':
model.delete(act[1])
target_obj.delete(act[1])
elif act[0] == 'delete_all':
target_ids = model.search([
(self.field, 'in', ids),
])
model.delete(target_ids)
target_obj.delete(target_obj.search([
search_clause(ids),
]))
elif act[0] == 'unlink':
if isinstance(act[1], (int, long)):
target_ids = [act[1]]
@@ -144,13 +175,13 @@ class One2Many(Field):
target_ids = list(act[1])
if not target_ids:
continue
target_ids = model.search([
(self.field, 'in', ids),
('id', 'in', target_ids),
])
model.write(target_ids, {
self.field: False,
})
target_ids = target_obj.search([
search_clause(ids),
('id', 'in', target_ids),
])
target_obj.write(target_ids, {
self.field: None,
})
elif act[0] == 'add':
if isinstance(act[1], (int, long)):
target_ids = [act[1]]
@@ -159,32 +190,32 @@ class One2Many(Field):
if not target_ids:
continue
for record_id in ids:
model.write(target_ids, {
self.field: record_id,
})
target_obj.write(target_ids, {
self.field: field_value(record_id),
})
elif act[0] == 'unlink_all':
target_ids = model.search([
(self.field, 'in', ids),
])
model.write(target_ids, {
self.field: False,
})
target_ids = target_obj.search([
search_clause(ids),
])
target_obj.write(target_ids, {
self.field: None,
})
elif act[0] == 'set':
if not act[1]:
target_ids = [0]
else:
target_ids = list(act[1])
for record_id in ids:
target_ids2 = model.search([
(self.field, '=', record_id),
('id', 'not in', target_ids),
])
model.write(target_ids2, {
self.field: False,
})
if act[1]:
model.write(target_ids, {
self.field: record_id,
target_ids2 = target_obj.search([
search_clause([record_id]),
('id', 'not in', target_ids),
])
target_obj.write(target_ids2, {
self.field: None,
})
if act[1]:
target_obj.write(target_ids, {
self.field: field_value(record_id),
})
else:
raise Exception('Bad arguments')
+64 -45
View File
@@ -1427,6 +1427,17 @@ class ModelSQL(ModelStorage):
else:
relation_obj = target_obj
origin, target = field.field, 'id'
if origin in relation_obj._columns:
rev_field = relation_obj._columns[origin]
else:
rev_field = relation_obj._inherit_fields[origin][2]
if rev_field._type == 'reference':
sql_type = FIELDS[
self.id._type].sql_type(self.id)[0]
origin = ('CAST(SPLIT_PART("%s", \',\', 2) AS %s)'
% (origin, sql_type))
else:
origin = '"%s"' % origin
if hasattr(field, 'search'):
domain.extend([(fargs[0], 'in', target_obj.search([
(fargs[1], domain[i][1], domain[i][2]),
@@ -1436,7 +1447,7 @@ class ModelSQL(ModelStorage):
query1, query2 = target_obj.search([
(fargs[1], domain[i][1], domain[i][2]),
], order=[], query_string=True)
query1 = ('SELECT "%s" FROM "%s" WHERE "%s" IN (%s)' %
query1 = ('SELECT %s FROM "%s" WHERE "%s" IN (%s)' %
(origin, relation_obj._table, target, query1))
domain[i] = ('id', 'inselect', (query1, query2))
i += 1
@@ -1450,57 +1461,46 @@ class ModelSQL(ModelStorage):
domain.extend(field.search(table, clause[0], clause))
elif field._type == 'one2many':
field_obj = pool.get(field.model_name)
if isinstance(domain[i][2], basestring):
# get the ids of the records of the "distant" resource
ids2 = [x[0] for x in field_obj.search([
('rec_name', domain[i][1], domain[i][2]),
], order=[])]
else:
ids2 = domain[i][2]
table_query = ''
table_args = []
if field_obj.table_query():
table_query, table_args = field_obj.table_query()
table_query = '(' + table_query + ') AS '
if field.field in field_obj._columns:
rev_field = field_obj._columns[field.field]
else:
rev_field = field_obj._inherit_fields[field.field][2]
if rev_field._type == 'reference':
sql_type = FIELDS[self.id._type].sql_type(self.id)[0]
select = ('CAST(SPLIT_PART("%s", \',\', 2) AS %s)'
% (field.field, sql_type))
else:
select = '"' + field.field + '"'
if ids2 == True or ids2 == False:
query1 = 'SELECT "' + field.field + '" ' \
if isinstance(domain[i][2], bool) or domain[i][2] is None:
query1 = 'SELECT ' + select + ' ' \
'FROM ' + table_query + \
'"' + field_obj._table + '" ' \
'WHERE "' + field.field + '" IS NOT NULL'
query2 = table_args
clause = 'inselect'
if ids2 == False:
if not domain[i][2]:
clause = 'notinselect'
domain[i] = ('id', clause, (query1, query2))
elif not ids2:
domain[i] = ('id', '=', '0')
else:
if len(ids2) < cursor.IN_MAX:
red_sql, red_ids = reduce_ids('id', ids2)
query1 = 'SELECT "' + field.field + '" ' \
'FROM ' + table_query + \
'"' + field_obj._table + '" ' \
'WHERE ' + red_sql
query2 = table_args + red_ids
domain[i] = ('id', 'inselect', (query1, query2))
if isinstance(domain[i][2], basestring):
target_field = 'rec_name'
else:
ids3 = []
for i in range(0, len(ids2), cursor.IN_MAX):
sub_ids2 = ids2[i:i + cursor.IN_MAX]
red_sql, red_ids = reduce_ids('id', sub_ids2)
cursor.execute(
'SELECT "' + field.field + '" ' \
'FROM ' + table_query + \
'"' + field_obj._table + '" ' \
'WHERE ' + red_sql,
table_args + red_ids)
ids3.extend([x[0] for x in cursor.fetchall()])
domain[i] = ('id', 'in', ids3)
target_field = 'id'
query1, query2 = field_obj.search([
(target_field, domain[i][1], domain[i][2]),
], order=[], query_string=True)
query1 = ('SELECT ' + select + ' '
'FROM ' + table_query +
'"' + field_obj._table + '" '
'WHERE id IN (' + query1 + ')')
query2 = table_args + query2
domain[i] = ('id', 'inselect', (query1, query2))
i += 1
elif field._type in ('many2many', 'one2one'):
# XXX must find a solution for long id list
@@ -1555,14 +1555,31 @@ class ModelSQL(ModelStorage):
domain[i] = ('id', 'not in', ids2 + _rec_get(ids2,
table, domain[i][0]))
else:
relation_obj = pool.get(field.relation_name)
table_query = ''
table_args = []
if relation_obj.table_query():
table_query, table_args = relation_obj.table_query()
table_query = '(' + table_query + ') AS '
if field.origin in relation_obj._columns:
origin_field = relation_obj._columns[field.origin]
else:
origin_field = \
relation_obj._inherit_fields[field.origin][2]
if origin_field._type == 'reference':
sql_type = FIELDS[self.id._type].sql_type(self.id)[0]
select = ('CAST(SPLIT_PART("%s", \',\', 2) AS %s)'
% (field.origin, sql_type))
else:
select = '"' + field.origin + '"'
if isinstance(domain[i][2], bool) or domain[i][2] is None:
relation_obj = pool.get(field.relation_name)
query1 = 'SELECT "' + field.origin + '" ' \
'FROM "' + relation_obj._table + '" '\
query1 = 'SELECT ' + select + ' ' \
'FROM ' + table_query + ' '\
'"' + relation_obj._table + '" ' \
'WHERE "' + field.origin + '" IS NOT NULL'
query2 = []
query2 = table_args
clause = 'inselect'
if domain[i][2] == False:
if not domain[i][2]:
clause = 'notinselect'
domain[i] = ('id', clause, (query1, query2))
else:
@@ -1575,9 +1592,11 @@ class ModelSQL(ModelStorage):
query1, query2 = target_obj.search([
(target_field, domain[i][1], domain[i][2]),
], order=[], query_string=True)
query1 = ('SELECT "%s" FROM "%s" WHERE "%s" IN (%s)' %
(field.origin, relation_obj._table,
field.target, query1))
query1 = ('SELECT ' + select + ' '
'FROM ' + table_query +
'"' + relation_obj._table + '" '
'WHERE "' + field.target + '" IN (' + query1 + ')')
query2 = table_args + query2
domain[i] = ('id', 'inselect', (query1, query2))
i += 1
+108
View File
@@ -472,6 +472,114 @@ class One2OneRequiredRelation(ModelSQL):
One2OneRequiredRelation()
class One2Many(ModelSQL):
'One2Many Relation'
_name = 'test.one2many'
_description = __doc__
name = fields.Char('Name', required=True)
targets = fields.One2Many('test.one2many.target', 'origin', 'Targets')
One2Many()
class One2ManyTarget(ModelSQL):
'One2Many Target'
_name = 'test.one2many.target'
_description = __doc__
name = fields.Char('Name', required=True)
origin = fields.Many2One('test.one2many', 'Origin')
One2ManyTarget()
class One2ManyReference(ModelSQL):
'One2Many Reference Relation'
_name = 'test.one2many_reference'
_description = __doc__
name = fields.Char('Name', required=True)
targets = fields.One2Many('test.one2many_reference.target', 'origin',
'Targets')
One2ManyReference()
class One2ManyReferenceTarget(ModelSQL):
'One2Many Reference Target'
_name = 'test.one2many_reference.target'
_description = __doc__
name = fields.Char('Name', required=True)
origin = fields.Reference('Origin', [
('test.one2many_reference', 'One2Many Reference'),
])
One2ManyReferenceTarget()
class Many2Many(ModelSQL):
'Many2Many'
_name = 'test.many2many'
_description = __doc__
name = fields.Char('Name', required=True)
targets = fields.Many2Many('test.many2many.relation', 'origin', 'target',
'Targets')
Many2Many()
class Many2ManyTarget(ModelSQL):
'Many2Many Target'
_name = 'test.many2many.target'
_description = __doc__
name = fields.Char('Name', required=True)
Many2ManyTarget()
class Many2ManyRelation(ModelSQL):
'Many2Many Relation'
_name = 'test.many2many.relation'
_description = __doc__
origin = fields.Many2One('test.many2many', 'Origin')
target = fields.Many2One('test.many2many.target', 'Target')
Many2ManyRelation()
class Many2ManyReference(ModelSQL):
'Many2Many Reference'
_name = 'test.many2many_reference'
_description = __doc__
name = fields.Char('Name', required=True)
targets = fields.Many2Many('test.many2many_reference.relation', 'origin',
'target', 'Targets')
Many2ManyReference()
class Many2ManyReferenceTarget(ModelSQL):
'Many2Many Reference Target'
_name = 'test.many2many_reference.target'
_description = __doc__
name = fields.Char('Name', required=True)
Many2ManyReferenceTarget()
class Many2ManyReferenceRelation(ModelSQL):
'Many2Many Relation'
_name = 'test.many2many_reference.relation'
_description = __doc__
origin = fields.Reference('Origin', [
('test.many2many_reference', 'Many2Many Reference'),
])
target = fields.Many2One('test.many2many_reference.target',
'Reference Target')
Many2ManyReferenceRelation()
class Property(ModelSQL):
'Property'
_name = 'test.property'
+330 -1
View File
@@ -76,6 +76,18 @@ class FieldsTestCase(unittest.TestCase):
self.one2one_target = POOL.get('test.one2one.target')
self.one2one_required = POOL.get('test.one2one_required')
self.one2many = POOL.get('test.one2many')
self.one2many_target = POOL.get('test.one2many.target')
self.one2many_reference = POOL.get('test.one2many_reference')
self.one2many_reference_target = POOL.get(
'test.one2many_reference.target')
self.many2many = POOL.get('test.many2many')
self.many2many_target = POOL.get('test.many2many.target')
self.many2many_reference = POOL.get('test.many2many_reference')
self.many2many_reference_target = POOL.get(
'test.many2many_reference.target')
self.property_ = POOL.get('test.property')
def test0010boolean(self):
@@ -2457,7 +2469,324 @@ class FieldsTestCase(unittest.TestCase):
transaction.cursor.rollback()
def test0110property(self):
def test0120one2many(self):
'''
Test One2Many.
'''
with Transaction().start(DB_NAME, USER,
context=CONTEXT) as transaction:
for one2many, one2many_target in (
(self.one2many, self.one2many_target),
(self.one2many_reference, self.one2many_reference_target),
):
one2many1_id = one2many.create({
'name': 'origin1',
'targets': [
('create', {
'name': 'target1',
}),
],
})
self.assert_(one2many1_id)
one2many1 = one2many.read(one2many1_id, ['targets'])
self.assertEqual(len(one2many1['targets']), 1)
target1_id, = one2many1['targets']
one2many_ids = one2many.search([
('targets', '=', 'target1'),
])
self.assertEqual(one2many_ids, [one2many1_id])
one2many_ids = one2many.search([
('targets', '!=', 'target1'),
])
self.assertEqual(one2many_ids, [])
one2many_ids = one2many.search([
('targets', 'in', [target1_id]),
])
self.assertEqual(one2many_ids, [one2many1_id])
one2many_ids = one2many.search([
('targets', 'in', [0]),
])
self.assertEqual(one2many_ids, [])
one2many_ids = one2many.search([
('targets', 'not in', [target1_id]),
])
self.assertEqual(one2many_ids, [])
one2many_ids = one2many.search([
('targets', 'not in', [0]),
])
self.assertEqual(one2many_ids, [one2many1_id])
one2many_ids = one2many.search([
('targets.name', '=', 'target1'),
])
self.assertEqual(one2many_ids, [one2many1_id])
one2many_ids = one2many.search([
('targets.name', '!=', 'target1'),
])
self.assertEqual(one2many_ids, [])
one2many2_id = one2many.create({
'name': 'origin2',
})
self.assert_(one2many2_id)
one2many2 = one2many.read(one2many2_id, ['targets'])
self.assertEqual(one2many2['targets'], [])
one2many_ids = one2many.search([
('targets', '=', None),
])
self.assertEqual(one2many_ids, [one2many2_id])
one2many.write(one2many1_id, {
'targets': [
('write', [target1_id], {
'name': 'target1bis',
}),
],
})
target1 = one2many_target.read(target1_id, ['name'])
self.assertEqual(target1['name'], 'target1bis')
target2_id = one2many_target.create({
'name': 'target2',
})
one2many.write(one2many1_id, {
'targets': [
('add', [target2_id]),
],
})
one2many1 = one2many.read(one2many1_id, ['targets'])
self.assertEqual(one2many1['targets'],
[target1_id, target2_id])
one2many.write(one2many1_id, {
'targets': [
('unlink', [target2_id]),
],
})
one2many1 = one2many.read(one2many1_id, ['targets'])
self.assertEqual(one2many1['targets'], [target1_id])
target2_id, = one2many_target.search([
('id', '=', target2_id),
])
self.assert_(target2_id)
one2many.write(one2many1_id, {
'targets': [
('unlink_all',),
],
})
one2many1 = one2many.read(one2many1_id, ['targets'])
self.assertEqual(one2many1['targets'], [])
target_ids = one2many_target.search([
('id', 'in', [target1_id, target2_id]),
])
self.assertEqual(target_ids, [target1_id, target2_id])
one2many.write(one2many1_id, {
'targets': [
('set', [target1_id, target2_id]),
],
})
one2many1 = one2many.read(one2many1_id, ['targets'])
self.assertEqual(one2many1['targets'],
[target1_id, target2_id])
one2many.write(one2many1_id, {
'targets': [
('delete', [target2_id]),
],
})
one2many1 = one2many.read(one2many1_id, ['targets'])
self.assertEqual(one2many1['targets'], [target1_id])
target_ids = one2many_target.search([
('id', '=', target2_id),
])
self.assertEqual(target_ids, [])
one2many.write(one2many1_id, {
'targets': [
('delete_all',),
],
})
one2many1 = one2many.read(one2many1_id, ['targets'])
self.assertEqual(one2many1['targets'], [])
target_ids = one2many_target.search([
('id', '=', target1_id),
])
self.assertEqual(target_ids, [])
transaction.cursor.rollback()
def test0130many2many(self):
'''
Test Many2Many.
'''
with Transaction().start(DB_NAME, USER,
context=CONTEXT) as transaction:
for many2many, many2many_target in (
(self.many2many, self.many2many_target),
(self.many2many_reference,
self.many2many_reference_target),
):
many2many1_id = many2many.create({
'name': 'origin1',
'targets': [
('create', {
'name': 'target1',
}),
],
})
self.assert_(many2many1_id)
many2many1 = many2many.read(many2many1_id, ['targets'])
self.assertEqual(len(many2many1['targets']), 1)
target1_id, = many2many1['targets']
many2many_ids = many2many.search([
('targets', '=', 'target1'),
])
self.assertEqual(many2many_ids, [many2many1_id])
many2many_ids = many2many.search([
('targets', '!=', 'target1'),
])
self.assertEqual(many2many_ids, [])
many2many_ids = many2many.search([
('targets', 'in', [target1_id]),
])
self.assertEqual(many2many_ids, [many2many1_id])
many2many_ids = many2many.search([
('targets', 'in', [0]),
])
self.assertEqual(many2many_ids, [])
many2many_ids = many2many.search([
('targets', 'not in', [target1_id]),
])
self.assertEqual(many2many_ids, [])
many2many_ids = many2many.search([
('targets', 'not in', [0]),
])
self.assertEqual(many2many_ids, [many2many1_id])
many2many_ids = many2many.search([
('targets.name', '=', 'target1'),
])
self.assertEqual(many2many_ids, [many2many1_id])
many2many_ids = many2many.search([
('targets.name', '!=', 'target1'),
])
self.assertEqual(many2many_ids, [])
many2many2_id = many2many.create({
'name': 'origin2',
})
self.assert_(many2many2_id)
many2many2 = many2many.read(many2many2_id, ['targets'])
self.assertEqual(many2many2['targets'], [])
many2many_ids = many2many.search([
('targets', '=', None),
])
self.assertEqual(many2many_ids, [many2many2_id])
many2many.write(many2many1_id, {
'targets': [
('write', [target1_id], {
'name': 'target1bis',
}),
],
})
target1 = many2many_target.read(target1_id, ['name'])
self.assertEqual(target1['name'], 'target1bis')
target2_id = many2many_target.create({
'name': 'target2',
})
many2many.write(many2many1_id, {
'targets': [
('add', [target2_id]),
],
})
many2many1 = many2many.read(many2many1_id, ['targets'])
self.assertEqual(many2many1['targets'],
[target1_id, target2_id])
many2many.write(many2many1_id, {
'targets': [
('unlink', [target2_id]),
],
})
many2many1 = many2many.read(many2many1_id, ['targets'])
self.assertEqual(many2many1['targets'], [target1_id])
target2_id, = many2many_target.search([
('id', '=', target2_id),
])
self.assert_(target2_id)
many2many.write(many2many1_id, {
'targets': [
('unlink_all',),
],
})
many2many1 = many2many.read(many2many1_id, ['targets'])
self.assertEqual(many2many1['targets'], [])
target_ids = many2many_target.search([
('id', 'in', [target1_id, target2_id]),
])
self.assertEqual(target_ids, [target1_id, target2_id])
many2many.write(many2many1_id, {
'targets': [
('set', [target1_id, target2_id]),
],
})
many2many1 = many2many.read(many2many1_id, ['targets'])
self.assertEqual(many2many1['targets'],
[target1_id, target2_id])
many2many.write(many2many1_id, {
'targets': [
('delete', [target2_id]),
],
})
many2many1 = many2many.read(many2many1_id, ['targets'])
self.assertEqual(many2many1['targets'], [target1_id])
target_ids = many2many_target.search([
('id', '=', target2_id),
])
self.assertEqual(target_ids, [])
many2many.write(many2many1_id, {
'targets': [
('delete_all',),
],
})
many2many1 = many2many.read(many2many1_id, ['targets'])
self.assertEqual(many2many1['targets'], [])
target_ids = many2many_target.search([
('id', '=', target1_id),
])
self.assertEqual(target_ids, [])
transaction.cursor.rollback()
def test0140property(self):
'''
Test Property with supported field types.
'''