Allow to use Reference field in One2Many & Many2Many
review378002
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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.
|
||||
'''
|
||||
|
||||
Reference in New Issue
Block a user