Remove _inherits
review670002
This commit is contained in:
1 parent
9af0cc3039
commit
a95ae0dad9
17 files changed
+261
-965
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Remove _inherits
|
||||
* Add dynamic label
|
||||
* Add prefix, suffix on tree view
|
||||
* Replace _constraints with validate in ModelStorage
|
||||
|
||||
@@ -17,17 +17,6 @@ Class attributes are:
|
||||
It contains the a unique name to reference the model throughout the
|
||||
platform.
|
||||
|
||||
.. attribute:: Model._inherits
|
||||
|
||||
It contains a dictionary with one or more :attr:`Model._name` as keys. For each
|
||||
key a :class:`~trytond.model.fields.Many2One` field is defined as value. The
|
||||
:class:`trytond.model.fields.Many2One` fields must be defined in the the current
|
||||
model fields. A referenced model with ``_inherits`` is a generalization_ of the
|
||||
current model which is *specialized*. In the specialized model it is possible to
|
||||
interact with all attributes and methods of the general model.
|
||||
|
||||
.. _generalization: http://en.wikipedia.org/wiki/Class_diagram#Generalization
|
||||
|
||||
.. attribute:: Model.__rpc__
|
||||
|
||||
It contains a dictionary with method name as key and an instance of
|
||||
|
||||
+12
-92
@@ -340,7 +340,6 @@ class Fs2bdAccessor:
|
||||
self.fs2db[module] = {}
|
||||
module_data_ids = self.ModelData.search([
|
||||
('module', '=', module),
|
||||
('inherit', '=', None),
|
||||
], order=[('db_id', 'ASC')])
|
||||
|
||||
record_ids = {}
|
||||
@@ -485,10 +484,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
"""
|
||||
Model = record.__class__
|
||||
# search the field type in the object or in a parent
|
||||
if key in Model._fields:
|
||||
field_type = Model._fields[key]._type
|
||||
else:
|
||||
field_type = Model._inherit_fields[key][2]._type
|
||||
field_type = Model._fields[key]._type
|
||||
|
||||
# handle the value regarding to the type
|
||||
if field_type == 'many2one':
|
||||
@@ -520,7 +516,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
# problem when the corresponding recordds will be deleted:
|
||||
module_data = self.ModelData.search([
|
||||
('module', '=', self.module),
|
||||
('inherit', '=', None),
|
||||
], order=[('id', 'DESC')])
|
||||
return set(rec.fs_id for rec in module_data)
|
||||
|
||||
@@ -558,8 +553,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
db_id, db_model, mdata_id, old_values = [
|
||||
self.fs2db.get(module, fs_id)[x]
|
||||
for x in ["db_id", "model", "id", "values"]]
|
||||
inherit_db_ids = {}
|
||||
inherit_mdata_ids = []
|
||||
|
||||
if not old_values:
|
||||
old_values = {}
|
||||
@@ -592,31 +585,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
|
||||
record = self.fs2db.get_browserecord(
|
||||
module, Model.__name__, record.id)
|
||||
for table, field_name, field in \
|
||||
Model._inherit_fields.values():
|
||||
inherit_db_ids[table] = getattr(record, field_name).id
|
||||
|
||||
for table in inherit_db_ids.keys():
|
||||
data = self.ModelData.search([
|
||||
('fs_id', '=', fs_id),
|
||||
('module', '=', module),
|
||||
('model', '=', table),
|
||||
], limit=1)
|
||||
if data:
|
||||
self.ModelData.write(data, {
|
||||
'db_id': inherit_db_ids[table],
|
||||
'inherit': True,
|
||||
})
|
||||
data, = data
|
||||
else:
|
||||
data, = self.ModelData.create([{
|
||||
'fs_id': fs_id,
|
||||
'module': module,
|
||||
'model': table,
|
||||
'db_id': inherit_db_ids[table],
|
||||
'inherit': True,
|
||||
}])
|
||||
inherit_mdata_ids.append((table, data.id))
|
||||
|
||||
data = self.ModelData.search([
|
||||
('fs_id', '=', fs_id),
|
||||
@@ -643,22 +611,13 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
|
||||
# we cannot update a field if it was changed by a user...
|
||||
if key not in old_values:
|
||||
if key in Model._fields:
|
||||
expected_value = Model._defaults.get(
|
||||
key, lambda *a: None)()
|
||||
else:
|
||||
Inherit = self.pool.get(
|
||||
Model._inherit_fields[key][0])
|
||||
expected_value = Inherit._defaults.get(
|
||||
key, lambda *a: None)()
|
||||
expected_value = Model._defaults.get(key,
|
||||
lambda *a: None)()
|
||||
else:
|
||||
expected_value = old_values[key]
|
||||
|
||||
# Migration from 2.0: Reference field change value
|
||||
if key in Model._fields:
|
||||
field_type = Model._fields[key]._type
|
||||
else:
|
||||
field_type = Model._inherit_fields[key][2]._type
|
||||
field_type = Model._fields[key]._type
|
||||
if field_type == 'reference':
|
||||
if (expected_value and expected_value.endswith(',0')
|
||||
and not db_field):
|
||||
@@ -688,19 +647,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
self.fs2db.reset_browsercord(
|
||||
module, Model.__name__, [record.id])
|
||||
|
||||
if not inherit_db_ids:
|
||||
for table, field_name, field in \
|
||||
Model._inherit_fields.values():
|
||||
inherit_db_ids[table] = getattr(record, field_name).id
|
||||
if not inherit_mdata_ids:
|
||||
for table in inherit_db_ids.keys():
|
||||
data, = self.ModelData.search([
|
||||
('fs_id', '=', fs_id),
|
||||
('module', '=', module),
|
||||
('model', '=', table),
|
||||
], limit=1)
|
||||
inherit_mdata_ids.append((table, data.id))
|
||||
|
||||
if to_update:
|
||||
# re-read it: this ensure that we store the real value
|
||||
# in the model_data table:
|
||||
@@ -725,16 +671,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
'values': str(values),
|
||||
'date_update': datetime.datetime.now(),
|
||||
})
|
||||
for table, inherit_mdata_id in inherit_mdata_ids:
|
||||
self.ModelData.write(
|
||||
[self.ModelData(inherit_mdata_id)], {
|
||||
'fs_id': fs_id,
|
||||
'model': table,
|
||||
'module': module,
|
||||
'db_id': inherit_db_ids[table],
|
||||
'values': str(values),
|
||||
'date_update': datetime.datetime.now(),
|
||||
})
|
||||
# reset_browsercord to keep cache memory low
|
||||
self.fs2db.reset_browsercord(module, Model.__name__, [record.id])
|
||||
|
||||
@@ -742,11 +678,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
# this record is new, create it in the db:
|
||||
with Transaction().set_context(module=module, language='en_US'):
|
||||
record, = Model.create([values])
|
||||
inherit_db_ids = {}
|
||||
|
||||
for table, field_name, field in (
|
||||
Model._inherit_fields.values()):
|
||||
inherit_db_ids[table] = getattr(record, field_name).id
|
||||
|
||||
# re-read it: this ensure that we store the real value
|
||||
# in the model_data table:
|
||||
@@ -754,25 +685,14 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
for key in values:
|
||||
values[key] = self._clean_value(key, record)
|
||||
|
||||
to_create = [{
|
||||
'fs_id': fs_id,
|
||||
'model': model,
|
||||
'module': module,
|
||||
'db_id': record.id,
|
||||
'values': str(values),
|
||||
'noupdate': self.noupdate,
|
||||
}]
|
||||
for table in inherit_db_ids.keys():
|
||||
to_create.append({
|
||||
'fs_id': fs_id,
|
||||
'model': table,
|
||||
'module': module,
|
||||
'db_id': inherit_db_ids[table],
|
||||
'values': str(values),
|
||||
'inherit': True,
|
||||
'noupdate': self.noupdate,
|
||||
})
|
||||
mdata = self.ModelData.create(to_create)[0]
|
||||
mdata, = self.ModelData.create([{
|
||||
'fs_id': fs_id,
|
||||
'model': model,
|
||||
'module': module,
|
||||
'db_id': record.id,
|
||||
'values': str(values),
|
||||
'noupdate': self.noupdate,
|
||||
}])
|
||||
|
||||
# update fs2db:
|
||||
self.fs2db.set(module, fs_id, {
|
||||
|
||||
+123
-219
@@ -4,8 +4,9 @@ import base64
|
||||
import os
|
||||
from operator import itemgetter
|
||||
from collections import defaultdict
|
||||
from functools import partial
|
||||
|
||||
from ..model import ModelView, ModelSQL, fields
|
||||
from ..model import ModelView, ModelStorage, ModelSQL, fields
|
||||
from ..tools import file_open, safe_eval
|
||||
from ..backend import TableHandler
|
||||
from ..pyson import PYSONEncoder, CONTEXT, PYSON
|
||||
@@ -82,7 +83,7 @@ class Action(ModelSQL, ModelView):
|
||||
@classmethod
|
||||
def get_action_values(cls, type_, action_ids):
|
||||
Action = Pool().get(type_)
|
||||
columns = set(Action._fields.keys() + Action._inherit_fields.keys())
|
||||
columns = set(Action._fields.keys())
|
||||
columns.add('icon.rec_name')
|
||||
to_remove = ()
|
||||
if type_ == 'ir.action.report':
|
||||
@@ -230,10 +231,125 @@ class ActionKeyword(ModelSQL, ModelView):
|
||||
return keywords
|
||||
|
||||
|
||||
class ActionReport(ModelSQL, ModelView):
|
||||
class ActionMixin(ModelSQL):
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super(ActionMixin, cls).__setup__()
|
||||
for name in dir(Action):
|
||||
field = getattr(Action, name)
|
||||
if (isinstance(field, fields.Field)
|
||||
and not getattr(cls, name, None)):
|
||||
setattr(cls, name, fields.Function(field, 'get_action',
|
||||
setter='set_action', searcher='search_action'))
|
||||
default_func = 'default_' + name
|
||||
if getattr(Action, default_func, None):
|
||||
setattr(cls, default_func,
|
||||
partial(ActionMixin.default_action, name))
|
||||
|
||||
@staticmethod
|
||||
def default_action(name):
|
||||
pool = Pool()
|
||||
Action = pool.get('ir.action')
|
||||
return getattr(Action, 'default_' + name, None)()
|
||||
|
||||
@classmethod
|
||||
def get_action(cls, ids, names):
|
||||
records = cls.browse(ids)
|
||||
result = {}
|
||||
for name in names:
|
||||
result[name] = values = {}
|
||||
for record in records:
|
||||
value = getattr(record, 'action')
|
||||
convert = lambda v: v
|
||||
if value is not None:
|
||||
value = getattr(value, name)
|
||||
if isinstance(value, ModelStorage):
|
||||
if cls._fields[name]._type == 'reference':
|
||||
convert = str
|
||||
else:
|
||||
convert = int
|
||||
elif isinstance(value, (list, tuple)):
|
||||
convert = lambda v: [r.id for r in v]
|
||||
values[record.id] = convert(value)
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def set_action(cls, records, name, value):
|
||||
pool = Pool()
|
||||
Action = pool.get('ir.action')
|
||||
Action.write([r.action for r in records], {
|
||||
name: value,
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def search_action(cls, name, clause):
|
||||
return [('action.' + name,) + tuple(clause[1:])]
|
||||
|
||||
@classmethod
|
||||
def create(cls, vlist):
|
||||
pool = Pool()
|
||||
Action = pool.get('ir.action')
|
||||
new_records = []
|
||||
for values in vlist:
|
||||
later = {}
|
||||
action_values = {}
|
||||
values = values.copy()
|
||||
for field in values:
|
||||
if field in Action._fields:
|
||||
action_values[field] = values[field]
|
||||
if hasattr(getattr(cls, field), 'set'):
|
||||
later[field] = values[field]
|
||||
for field in later:
|
||||
del values[field]
|
||||
action_values['type'] = cls.default_type()
|
||||
cursor = Transaction().cursor
|
||||
if cursor.nextid(cls._table):
|
||||
cursor.setnextid(cls._table, cursor.currid(Action._table))
|
||||
action, = Action.create([action_values])
|
||||
values['action'] = action.id
|
||||
record, = super(ActionMixin, cls).create([values])
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
|
||||
'WHERE id = %s', (action.id, record.id))
|
||||
cursor.update_auto_increment(cls._table, action.id)
|
||||
record = cls(action.id)
|
||||
new_records.append(record)
|
||||
cls.write([record], later)
|
||||
return new_records
|
||||
|
||||
@classmethod
|
||||
def write(cls, records, values):
|
||||
pool = Pool()
|
||||
ActionKeyword = pool.get('ir.action.keyword')
|
||||
super(ActionMixin, cls).write(records, values)
|
||||
ActionKeyword._get_keyword_cache.clear()
|
||||
|
||||
@classmethod
|
||||
def delete(cls, records):
|
||||
pool = Pool()
|
||||
Action = pool.get('ir.action')
|
||||
actions = [x.action for x in records]
|
||||
super(ActionMixin, cls).delete(records)
|
||||
Action.delete(actions)
|
||||
|
||||
@classmethod
|
||||
def copy(cls, records, default=None):
|
||||
pool = Pool()
|
||||
Action = pool.get('ir.action')
|
||||
if default is None:
|
||||
default = {}
|
||||
default = default.copy()
|
||||
new_records = []
|
||||
for record in records:
|
||||
default['action'] = Action.copy([record.action])[0].id
|
||||
new_records.extend(super(ActionMixin, cls).copy([record],
|
||||
default=default))
|
||||
return new_records
|
||||
|
||||
|
||||
class ActionReport(ActionMixin, ModelSQL, ModelView):
|
||||
"Action report"
|
||||
__name__ = 'ir.action.report'
|
||||
_inherits = {'ir.action': 'action'}
|
||||
model = fields.Char('Model')
|
||||
report_name = fields.Char('Internal Name', required=True)
|
||||
report = fields.Char('Path')
|
||||
@@ -499,8 +615,6 @@ class ActionReport(ModelSQL, ModelView):
|
||||
|
||||
@classmethod
|
||||
def copy(cls, reports, default=None):
|
||||
Action = Pool().get('ir.action')
|
||||
|
||||
if default is None:
|
||||
default = {}
|
||||
default = default.copy()
|
||||
@@ -511,62 +625,23 @@ class ActionReport(ModelSQL, ModelView):
|
||||
if report.report:
|
||||
default['report_content'] = None
|
||||
default['report_name'] = report.report_name
|
||||
default['action'] = Action.copy([report.action])[0].id
|
||||
new_reports.extend(super(ActionReport, cls).copy([report],
|
||||
default=default))
|
||||
return new_reports
|
||||
|
||||
@classmethod
|
||||
def create(cls, vlist):
|
||||
new_vlist = []
|
||||
for vals in vlist:
|
||||
later = {}
|
||||
vals = vals.copy()
|
||||
for field in vals:
|
||||
if (field in cls._fields
|
||||
and hasattr(cls._fields[field], 'set')):
|
||||
later[field] = vals[field]
|
||||
for field in later:
|
||||
del vals[field]
|
||||
cursor = Transaction().cursor
|
||||
if cursor.nextid(cls._table):
|
||||
cursor.setnextid(cls._table, cursor.currid('ir_action'))
|
||||
report, = super(ActionReport, cls).create([vals])
|
||||
cursor.execute('SELECT action FROM "' + cls._table + '" '
|
||||
'WHERE id = %s', (report.id,))
|
||||
new_id, = cursor.fetchone()
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
|
||||
'WHERE id = %s', (new_id, report.id))
|
||||
cursor.update_auto_increment(cls._table, new_id)
|
||||
report = cls(new_id)
|
||||
new_vlist.append(report)
|
||||
cls.write([report], later)
|
||||
return new_vlist
|
||||
|
||||
@classmethod
|
||||
def write(cls, reports, vals):
|
||||
pool = Pool()
|
||||
context = Transaction().context
|
||||
if 'module' in context:
|
||||
vals = vals.copy()
|
||||
vals['module'] = context['module']
|
||||
|
||||
super(ActionReport, cls).write(reports, vals)
|
||||
pool.get('ir.action.keyword')._get_keyword_cache.clear()
|
||||
|
||||
@classmethod
|
||||
def delete(cls, reports):
|
||||
Action = Pool().get('ir.action')
|
||||
|
||||
actions = [x.action for x in reports]
|
||||
super(ActionReport, cls).delete(reports)
|
||||
Action.delete(actions)
|
||||
|
||||
|
||||
class ActionActWindow(ModelSQL, ModelView):
|
||||
class ActionActWindow(ActionMixin, ModelSQL, ModelView):
|
||||
"Action act window"
|
||||
__name__ = 'ir.action.act_window'
|
||||
_inherits = {'ir.action': 'action'}
|
||||
domain = fields.Char('Domain Value')
|
||||
context = fields.Char('Context Value')
|
||||
res_model = fields.Char('Model')
|
||||
@@ -771,47 +846,6 @@ class ActionActWindow(ModelSQL, ModelView):
|
||||
or defaults.get(field, 'None'), CONTEXT))
|
||||
return pysons
|
||||
|
||||
@classmethod
|
||||
def create(cls, vlist):
|
||||
new_vlist = []
|
||||
for vals in vlist:
|
||||
later = {}
|
||||
vals = vals.copy()
|
||||
for field in vals:
|
||||
if (field in cls._fields
|
||||
and hasattr(cls._fields[field], 'set')):
|
||||
later[field] = vals[field]
|
||||
for field in later:
|
||||
del vals[field]
|
||||
cursor = Transaction().cursor
|
||||
if cursor.nextid(cls._table):
|
||||
cursor.setnextid(cls._table, cursor.currid('ir_action'))
|
||||
act_window, = super(ActionActWindow, cls).create([vals])
|
||||
cursor.execute('SELECT action FROM "' + cls._table + '" '
|
||||
'WHERE id = %s', (act_window.id,))
|
||||
new_id, = cursor.fetchone()
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
|
||||
'WHERE id = %s', (new_id, act_window.id))
|
||||
cursor.update_auto_increment(cls._table, new_id)
|
||||
act_window = cls(new_id)
|
||||
new_vlist.append(act_window)
|
||||
cls.write([act_window], later)
|
||||
return new_vlist
|
||||
|
||||
@classmethod
|
||||
def write(cls, act_windows, values):
|
||||
pool = Pool()
|
||||
super(ActionActWindow, cls).write(act_windows, values)
|
||||
pool.get('ir.action.keyword')._get_keyword_cache.clear()
|
||||
|
||||
@classmethod
|
||||
def delete(cls, act_windows):
|
||||
Action = Pool().get('ir.action')
|
||||
|
||||
actions = [x.action for x in act_windows]
|
||||
super(ActionActWindow, cls).delete(act_windows)
|
||||
Action.delete(actions)
|
||||
|
||||
@classmethod
|
||||
def get(cls, xml_id):
|
||||
'Get values from XML id or id'
|
||||
@@ -824,19 +858,6 @@ class ActionActWindow(ModelSQL, ModelView):
|
||||
action_id = int(xml_id)
|
||||
return Action.get_action_values(cls.__name__, [action_id])[0]
|
||||
|
||||
@classmethod
|
||||
def copy(cls, actions, default=None):
|
||||
Action = Pool().get('ir.action')
|
||||
if default is None:
|
||||
default = {}
|
||||
default = default.copy()
|
||||
new_actions = []
|
||||
for act_window in actions:
|
||||
default['action'] = Action.copy([act_window.action])[0].id
|
||||
new_actions.extend(super(ActionActWindow, cls).copy([act_window],
|
||||
default=default))
|
||||
return new_actions
|
||||
|
||||
|
||||
class ActionActWindowView(ModelSQL, ModelView):
|
||||
"Action act window view"
|
||||
@@ -901,10 +922,9 @@ class ActionActWindowDomain(ModelSQL, ModelView):
|
||||
return True
|
||||
|
||||
|
||||
class ActionWizard(ModelSQL, ModelView):
|
||||
class ActionWizard(ActionMixin, ModelSQL, ModelView):
|
||||
"Action wizard"
|
||||
__name__ = 'ir.action.wizard'
|
||||
_inherits = {'ir.action': 'action'}
|
||||
wiz_name = fields.Char('Wizard name', required=True)
|
||||
action = fields.Many2One('ir.action', 'Action', required=True,
|
||||
ondelete='CASCADE')
|
||||
@@ -916,68 +936,10 @@ class ActionWizard(ModelSQL, ModelView):
|
||||
def default_type():
|
||||
return 'ir.action.wizard'
|
||||
|
||||
@classmethod
|
||||
def create(cls, vlist):
|
||||
new_vlist = []
|
||||
for vals in vlist:
|
||||
later = {}
|
||||
vals = vals.copy()
|
||||
for field in vals:
|
||||
if (field in cls._fields
|
||||
and hasattr(cls._fields[field], 'set')):
|
||||
later[field] = vals[field]
|
||||
for field in later:
|
||||
del vals[field]
|
||||
cursor = Transaction().cursor
|
||||
if cursor.nextid(cls._table):
|
||||
cursor.setnextid(cls._table, cursor.currid('ir_action'))
|
||||
wizard, = super(ActionWizard, cls).create([vals])
|
||||
cursor.execute('SELECT action FROM "' + cls._table + '" '
|
||||
'WHERE id = %s', (wizard.id,))
|
||||
new_id, = cursor.fetchone()
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
|
||||
'WHERE id = %s', (new_id, wizard.id))
|
||||
cursor.update_auto_increment(cls._table, new_id)
|
||||
wizard = cls(new_id)
|
||||
new_vlist.append(wizard)
|
||||
cls.write([wizard], later)
|
||||
return new_vlist
|
||||
|
||||
@classmethod
|
||||
def write(cls, wizards, values):
|
||||
pool = Pool()
|
||||
super(ActionWizard, cls).write(wizards, values)
|
||||
pool.get('ir.action.keyword')._get_keyword_cache.clear()
|
||||
|
||||
@classmethod
|
||||
def delete(cls, wizards):
|
||||
pool = Pool()
|
||||
Action = pool.get('ir.action')
|
||||
|
||||
actions = [x.action for x in wizards]
|
||||
|
||||
super(ActionWizard, cls).delete(wizards)
|
||||
Action.delete(actions)
|
||||
|
||||
@classmethod
|
||||
def copy(cls, wizards, default=None):
|
||||
Action = Pool().get('ir.action')
|
||||
|
||||
if default is None:
|
||||
default = {}
|
||||
default = default.copy()
|
||||
new_wizards = []
|
||||
for wizard in wizards:
|
||||
default['action'] = Action.copy([wizard.action])[0].id
|
||||
new_wizards.extend(super(ActionWizard, cls).copy([wizard],
|
||||
default=default))
|
||||
return new_wizards
|
||||
|
||||
|
||||
class ActionURL(ModelSQL, ModelView):
|
||||
class ActionURL(ActionMixin, ModelSQL, ModelView):
|
||||
"Action URL"
|
||||
__name__ = 'ir.action.url'
|
||||
_inherits = {'ir.action': 'action'}
|
||||
url = fields.Char('Action Url', required=True)
|
||||
action = fields.Many2One('ir.action', 'Action', required=True,
|
||||
ondelete='CASCADE')
|
||||
@@ -989,61 +951,3 @@ class ActionURL(ModelSQL, ModelView):
|
||||
@staticmethod
|
||||
def default_target():
|
||||
return 'new'
|
||||
|
||||
@classmethod
|
||||
def create(cls, vlist):
|
||||
new_vlist = []
|
||||
for vals in vlist:
|
||||
later = {}
|
||||
vals = vals.copy()
|
||||
for field in vals:
|
||||
if (field in cls._fields
|
||||
and hasattr(cls._fields[field], 'set')):
|
||||
later[field] = vals[field]
|
||||
for field in later:
|
||||
del vals[field]
|
||||
cursor = Transaction().cursor
|
||||
if cursor.nextid(cls._table):
|
||||
cursor.setnextid(cls._table, cursor.currid('ir_action'))
|
||||
url, = super(ActionURL, cls).create([vals])
|
||||
cursor.execute('SELECT action FROM "' + cls._table + '" '
|
||||
'WHERE id = %s', (url.id,))
|
||||
new_id, = cursor.fetchone()
|
||||
cls.write([url], {}) # simulate write to clear the cache
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
|
||||
'WHERE id = %s', (new_id, url.id))
|
||||
cursor.update_auto_increment(cls._table, new_id)
|
||||
url = cls(new_id)
|
||||
new_vlist.append(url)
|
||||
cls.write([url], later)
|
||||
return new_vlist
|
||||
|
||||
@classmethod
|
||||
def write(cls, urls, values):
|
||||
pool = Pool()
|
||||
super(ActionURL, cls).write(urls, values)
|
||||
pool.get('ir.action.keyword')._get_keyword_cache.clear()
|
||||
|
||||
@classmethod
|
||||
def delete(cls, urls):
|
||||
pool = Pool()
|
||||
Action = pool.get('ir.action')
|
||||
|
||||
actions = [x.action for x in urls]
|
||||
|
||||
super(ActionURL, cls).delete(urls)
|
||||
Action.delete(actions)
|
||||
|
||||
@classmethod
|
||||
def copy(cls, urls, default=None):
|
||||
Action = Pool().get('ir.action')
|
||||
|
||||
if default is None:
|
||||
default = {}
|
||||
default = default.copy()
|
||||
new_urls = []
|
||||
for url in urls:
|
||||
default['action'] = Action.copy([url.action])[0].id
|
||||
new_urls.extend(super(ActionURL, cls).copy([url],
|
||||
default=default))
|
||||
return new_urls
|
||||
+14
-6
@@ -666,7 +666,6 @@ class ModelData(ModelSQL, ModelView):
|
||||
date_update = fields.DateTime('Update Date')
|
||||
date_init = fields.DateTime('Init Date')
|
||||
values = fields.Text('Values')
|
||||
inherit = fields.Boolean('Inherit')
|
||||
noupdate = fields.Boolean('No Update')
|
||||
_get_id_cache = Cache('ir_model_data.get_id', context=False)
|
||||
|
||||
@@ -678,14 +677,24 @@ class ModelData(ModelSQL, ModelView):
|
||||
'The triple (fs_id, module, model) must be unique!'),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module_name):
|
||||
cursor = Transaction().cursor
|
||||
|
||||
super(ModelData, cls).__register__(module_name)
|
||||
|
||||
table = TableHandler(cursor, cls, module_name)
|
||||
|
||||
# Migration from 2.6: remove inherit
|
||||
if table.column_exist('inherit'):
|
||||
cursor.execute('DELETE FROM "' + cls._table + '" '
|
||||
'WHERE inherit = %s', (True,))
|
||||
table.drop_column('inherit', True)
|
||||
|
||||
@staticmethod
|
||||
def default_date_init():
|
||||
return datetime.datetime.now()
|
||||
|
||||
@staticmethod
|
||||
def default_inherit():
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def default_noupdate():
|
||||
return False
|
||||
@@ -708,7 +717,6 @@ class ModelData(ModelSQL, ModelView):
|
||||
data = cls.search([
|
||||
('module', '=', module),
|
||||
('fs_id', '=', fs_id),
|
||||
('inherit', '=', False),
|
||||
], limit=1)
|
||||
if not data:
|
||||
raise Exception("Reference to %s not found"
|
||||
|
||||
@@ -75,10 +75,7 @@ class Many2Many(Field):
|
||||
order = self.order
|
||||
|
||||
Relation = Pool().get(self.relation_name)
|
||||
if self.origin in Relation._fields:
|
||||
origin_field = Relation._fields[self.origin]
|
||||
else:
|
||||
origin_field = Relation._inherit_fields[self.origin][2]
|
||||
origin_field = Relation._fields[self.origin]
|
||||
|
||||
relations = []
|
||||
for i in range(0, len(ids), Transaction().cursor.IN_MAX):
|
||||
@@ -116,10 +113,7 @@ class Many2Many(Field):
|
||||
return
|
||||
Relation = pool.get(self.relation_name)
|
||||
Target = self.get_target()
|
||||
if self.origin in Relation._fields:
|
||||
origin_field = Relation._fields[self.origin]
|
||||
else:
|
||||
origin_field = Relation._inherit_fields[self.origin][2]
|
||||
origin_field = Relation._fields[self.origin]
|
||||
|
||||
def search_clause(ids):
|
||||
if origin_field._type == 'reference':
|
||||
@@ -228,10 +222,7 @@ class Many2Many(Field):
|
||||
Relation = Pool().get(self.relation_name)
|
||||
if not self.target:
|
||||
return Relation
|
||||
if self.target in Relation._fields:
|
||||
return Relation._fields[self.target].get_target()
|
||||
else:
|
||||
return Relation._inherit_fields[self.target][2].get_target()
|
||||
return Relation._fields[self.target].get_target()
|
||||
|
||||
def __set__(self, inst, value):
|
||||
Target = self.get_target()
|
||||
|
||||
@@ -79,10 +79,7 @@ class One2Many(Field):
|
||||
'''
|
||||
pool = Pool()
|
||||
Relation = pool.get(self.model_name)
|
||||
if self.field in Relation._fields:
|
||||
field = Relation._fields[self.field]
|
||||
else:
|
||||
field = Relation._inherit_fields[self.field][2]
|
||||
field = Relation._fields[self.field]
|
||||
res = {}
|
||||
for i in ids:
|
||||
res[i] = []
|
||||
@@ -119,10 +116,7 @@ class One2Many(Field):
|
||||
if not values:
|
||||
return
|
||||
Target = self.get_target()
|
||||
if self.field in Target._fields:
|
||||
field = Target._fields[self.field]
|
||||
else:
|
||||
field = Target._inherit_fields[self.field][2]
|
||||
field = Target._fields[self.field]
|
||||
|
||||
def search_clause(ids):
|
||||
if field._type == 'reference':
|
||||
|
||||
+6
-85
@@ -16,33 +16,11 @@ from trytond.rpc import RPC
|
||||
__all__ = ['Model']
|
||||
|
||||
|
||||
class ModelMeta(PoolMeta):
|
||||
|
||||
def __getattr__(self, name):
|
||||
pool = Pool()
|
||||
for model_name, _ in self._inherits.iteritems():
|
||||
Model = pool.get(model_name)
|
||||
if isinstance(getattr(Model, name, None),
|
||||
collections.Callable):
|
||||
meth = getattr(Model, name)
|
||||
if not hasattr(meth, 'im_self') or meth.im_self:
|
||||
# Return classmethod bounded to inherited class
|
||||
return meth
|
||||
else:
|
||||
for cls in Model.__mro__:
|
||||
if name in cls.__dict__:
|
||||
# Return a method bounded to current class
|
||||
return cls.__dict__[name].__get__(None, self)
|
||||
raise AttributeError("'%s' Model has no attribute '%s'"
|
||||
% (self.__name__, name))
|
||||
|
||||
|
||||
class Model(WarningErrorMixin, URLMixin):
|
||||
"""
|
||||
Define a model in Tryton.
|
||||
"""
|
||||
__metaclass__ = ModelMeta
|
||||
_inherits = {}
|
||||
__metaclass__ = PoolMeta
|
||||
_rec_name = 'name'
|
||||
|
||||
id = fields.Integer('ID', readonly=True)
|
||||
@@ -76,48 +54,21 @@ class Model(WarningErrorMixin, URLMixin):
|
||||
if isinstance(getattr(cls, attr), fields.Field):
|
||||
cls._fields[attr] = getattr(cls, attr)
|
||||
|
||||
# Set _inherit_fields
|
||||
cls._inherit_fields = {}
|
||||
for model_name in cls._inherits:
|
||||
Model = pool.get(model_name)
|
||||
cls._inherit_fields.update(Model._inherit_fields)
|
||||
for field_name in Model._fields.keys():
|
||||
cls._inherit_fields[field_name] = (model_name,
|
||||
cls._inherits[model_name],
|
||||
Model._fields[field_name])
|
||||
for field_name in Model._inherit_fields.keys():
|
||||
cls._inherit_fields[field_name] = (model_name,
|
||||
cls._inherits[model_name],
|
||||
Model._inherit_fields[field_name][2])
|
||||
# Update models that uses this one in _inherits
|
||||
for _, Model in pool.iterobject():
|
||||
if cls.__name__ in Model._inherits:
|
||||
Model.__post_setup__()
|
||||
|
||||
# Set _defaults
|
||||
cls._defaults = {}
|
||||
fields_names = cls._fields.keys()
|
||||
fields_names += cls._inherit_fields.keys()
|
||||
for field_name in fields_names:
|
||||
default_method = getattr(cls, 'default_%s' % field_name, False)
|
||||
if not default_method and field_name in cls._inherit_fields:
|
||||
icls = pool.get(cls._inherit_fields[field_name][0])
|
||||
default_method = getattr(icls, 'default_%s' % field_name,
|
||||
False)
|
||||
if isinstance(default_method, collections.Callable):
|
||||
cls._defaults[field_name] = default_method
|
||||
|
||||
for k in cls._defaults:
|
||||
assert (k in cls._fields) or (k in cls._inherit_fields), \
|
||||
assert k in cls._fields, \
|
||||
'Default function defined in %s but field %s does not exist!' \
|
||||
% (cls.__name__, k,)
|
||||
|
||||
# Update __rpc__
|
||||
for field_name in cls._fields.keys() + cls._inherit_fields.keys():
|
||||
if field_name in cls._fields:
|
||||
field = cls._fields[field_name]
|
||||
else:
|
||||
field = cls._inherit_fields[field_name][2]
|
||||
for field_name, field in cls._fields.iteritems():
|
||||
if isinstance(field, (fields.Selection, fields.Reference)) \
|
||||
and not isinstance(field.selection, (list, tuple)) \
|
||||
and field.selection not in cls.__rpc__:
|
||||
@@ -364,10 +315,7 @@ class Model(WarningErrorMixin, URLMixin):
|
||||
for field_name in fields_names:
|
||||
if field_name in cls._defaults:
|
||||
value[field_name] = cls._defaults[field_name]()
|
||||
if field_name in cls._fields:
|
||||
field = cls._fields[field_name]
|
||||
else:
|
||||
field = cls._inherit_fields[field_name][2]
|
||||
field = cls._fields[field_name]
|
||||
if (field._type == 'boolean'
|
||||
and not field_name in value):
|
||||
value[field_name] = False
|
||||
@@ -397,8 +345,6 @@ class Model(WarningErrorMixin, URLMixin):
|
||||
pool = Pool()
|
||||
res = value.copy()
|
||||
val = {}
|
||||
for i in cls._inherits.keys():
|
||||
val.update(pool.get(i)._default_on_change(value))
|
||||
for field in value.keys():
|
||||
if field in cls._fields:
|
||||
if cls._fields[field].on_change:
|
||||
@@ -423,9 +369,6 @@ class Model(WarningErrorMixin, URLMixin):
|
||||
Translation = pool.get('ir.translation')
|
||||
FieldAccess = pool.get('ir.model.field.access')
|
||||
|
||||
for parent in cls._inherits:
|
||||
res.update(pool.get(parent).fields_get(fields_names))
|
||||
|
||||
#Add translation to cache
|
||||
language = Transaction().language
|
||||
trans_args = []
|
||||
@@ -619,19 +562,6 @@ class Model(WarningErrorMixin, URLMixin):
|
||||
def __getattr__(self, name):
|
||||
if name == 'id':
|
||||
return self.__dict__['id']
|
||||
if (name not in self._fields
|
||||
and name not in self._inherit_fields):
|
||||
# Search for method on inherits parents
|
||||
pool = Pool()
|
||||
for model_name, _ in self._inherits.iteritems():
|
||||
iModel = pool.get(model_name)
|
||||
if isinstance(getattr(iModel, name, None),
|
||||
collections.Callable):
|
||||
for cls in iModel.__mro__:
|
||||
if name in cls.__dict__:
|
||||
# Return a method bounded to current class
|
||||
return cls.__dict__[name].__get__(self,
|
||||
self.__class__)
|
||||
elif self._values and name in self._values:
|
||||
return self._values.get(name)
|
||||
raise AttributeError("'%s' Model has no attribute '%s': %s"
|
||||
@@ -641,11 +571,6 @@ class Model(WarningErrorMixin, URLMixin):
|
||||
if name == 'id':
|
||||
self.__dict__['id'] = value
|
||||
return
|
||||
if (name not in self._fields
|
||||
and name in self._inherit_fields):
|
||||
field = self._inherit_fields[name][2]
|
||||
field.__set__(self, value)
|
||||
return
|
||||
super(Model, self).__setattr__(name, value)
|
||||
|
||||
def __getitem__(self, name):
|
||||
@@ -654,8 +579,7 @@ class Model(WarningErrorMixin, URLMixin):
|
||||
return getattr(self, name)
|
||||
|
||||
def __contains__(self, name):
|
||||
return (name in self._fields
|
||||
or name in self._inherit_fields)
|
||||
return name in self._fields
|
||||
|
||||
def __int__(self):
|
||||
return int(self.id)
|
||||
@@ -700,10 +624,7 @@ class Model(WarningErrorMixin, URLMixin):
|
||||
values = {}
|
||||
if self._values:
|
||||
for fname, value in self._values.iteritems():
|
||||
if fname in self._fields:
|
||||
field = self._fields[fname]
|
||||
else:
|
||||
field = self._inherit_fields[fname][2]
|
||||
field = self._fields[fname]
|
||||
if isinstance(field, fields.Reference):
|
||||
if value is not None:
|
||||
value = str(value)
|
||||
|
||||
@@ -32,8 +32,7 @@ class ModelSingleton(ModelStorage):
|
||||
if not singleton:
|
||||
res = cls.default_get(fields_names, with_rec_name=False)
|
||||
if not fields_names:
|
||||
fields_names = (set(cls._fields.keys()
|
||||
+ cls._inherit_fields.keys()))
|
||||
fields_names = cls._fields.keys()
|
||||
for field_name in fields_names:
|
||||
if field_name not in res:
|
||||
res[field_name] = None
|
||||
|
||||
+25
-235
@@ -240,20 +240,11 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
# Get default values
|
||||
default = []
|
||||
avoid_table = []
|
||||
for (i, j) in cls._inherits.items():
|
||||
if j in values:
|
||||
avoid_table.append(i)
|
||||
for i in cls._fields.keys():
|
||||
if not i in values \
|
||||
and i not in ('create_uid', 'create_date',
|
||||
'write_uid', 'write_date'):
|
||||
default.append(i)
|
||||
for i in cls._inherit_fields.keys():
|
||||
if ((not i in values)
|
||||
and (not cls._inherit_fields[i][0] in avoid_table)
|
||||
and i in cls._defaults):
|
||||
default.append(i)
|
||||
|
||||
if len(default):
|
||||
defaults = cls.default_get(default, with_rec_name=False)
|
||||
@@ -269,26 +260,6 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
(upd0, upd1, upd2) = ('', '', [])
|
||||
|
||||
# Create inherits
|
||||
tocreate = {}
|
||||
for i in cls._inherits:
|
||||
if cls._inherits[i] not in values:
|
||||
tocreate[i] = {}
|
||||
|
||||
for i in values.keys():
|
||||
if i in cls._inherit_fields:
|
||||
(inherits, _, _) = cls._inherit_fields[i]
|
||||
if i in cls._fields:
|
||||
continue
|
||||
if inherits in tocreate:
|
||||
tocreate[inherits][i] = values[i]
|
||||
del values[i]
|
||||
|
||||
for inherits in tocreate:
|
||||
Inherits = pool.get(inherits)
|
||||
inherits_record, = Inherits.create([tocreate[inherits]])
|
||||
values[cls._inherits[inherits]] = inherits_record.id
|
||||
|
||||
# Insert record
|
||||
for fname, value in values.iteritems():
|
||||
field = cls._fields[fname]
|
||||
@@ -433,8 +404,7 @@ class ModelSQL(ModelStorage):
|
||||
cursor = Transaction().cursor
|
||||
|
||||
if not fields_names:
|
||||
fields_names = list(set(cls._fields.keys()
|
||||
+ cls._inherit_fields.keys()))
|
||||
fields_names = cls._fields.keys()
|
||||
|
||||
if not ids:
|
||||
return []
|
||||
@@ -451,19 +421,15 @@ class ModelSQL(ModelStorage):
|
||||
field, field_related = field_name.split('.', 1)
|
||||
fields_related.setdefault(field, [])
|
||||
fields_related[field].append(field_related)
|
||||
elif field_name in cls._fields:
|
||||
field = cls._fields[field_name]
|
||||
else:
|
||||
field = cls._inherit_fields[field_name][2]
|
||||
field = cls._fields[field_name]
|
||||
if hasattr(field, 'datetime_field') and field.datetime_field:
|
||||
datetime_fields.append(field.datetime_field)
|
||||
|
||||
# all inherited fields + all non inherited fields
|
||||
fields_pre = [x for x in
|
||||
fields_names + fields_related.keys() + datetime_fields
|
||||
if ((x in cls._fields
|
||||
and not hasattr(cls._fields[x], 'set'))
|
||||
or (x == '_timestamp'))] + cls._inherits.values()
|
||||
fields_pre = [x
|
||||
for x in fields_names + fields_related.keys() + datetime_fields
|
||||
if (x in cls._fields and not hasattr(cls._fields[x], 'set'))
|
||||
or (x == '_timestamp')]
|
||||
|
||||
res = []
|
||||
table_query = ''
|
||||
@@ -546,41 +512,9 @@ class ModelSQL(ModelStorage):
|
||||
for i in res:
|
||||
i[field] = res_trans.get(i['id'], False) or i[field]
|
||||
|
||||
for table in cls._inherits:
|
||||
field = cls._inherits[table]
|
||||
inherits_fields = list(
|
||||
set(cls._inherit_fields.keys()).intersection(
|
||||
set(fields_names + fields_related.keys() + datetime_fields)
|
||||
).difference(set(cls._fields.keys())))
|
||||
if not inherits_fields:
|
||||
for record in res:
|
||||
if field not in fields_names + fields_related.keys() + \
|
||||
datetime_fields:
|
||||
del record[field]
|
||||
continue
|
||||
inherit_related_fields = []
|
||||
for inherit_field in inherits_fields:
|
||||
if inherit_field in fields_related:
|
||||
for field_related in fields_related[inherit_field]:
|
||||
inherit_related_fields.append(
|
||||
inherit_field + '.' + field_related)
|
||||
res2 = pool.get(table).read([x[field] for x in res],
|
||||
fields_names=inherits_fields + inherit_related_fields)
|
||||
|
||||
res3 = {}
|
||||
for i in res2:
|
||||
res3[i['id']] = i
|
||||
del i['id']
|
||||
|
||||
for record in res:
|
||||
record.update(res3[record[field]])
|
||||
if field not in \
|
||||
fields_names + fields_related.keys() + datetime_fields:
|
||||
del record[field]
|
||||
|
||||
ids = [x['id'] for x in res]
|
||||
|
||||
# all non inherited fields for which there is a get attribute
|
||||
# all fields for which there is a get attribute
|
||||
fields_post = [x for x in
|
||||
fields_names + fields_related.keys() + datetime_fields
|
||||
if x in cls._fields and hasattr(cls._fields[x], 'get')]
|
||||
@@ -777,22 +711,17 @@ class ModelSQL(ModelStorage):
|
||||
upd0 = []
|
||||
upd1 = []
|
||||
upd_todo = []
|
||||
updend = []
|
||||
direct = []
|
||||
for field in values:
|
||||
if field in cls._fields:
|
||||
if not hasattr(cls._fields[field], 'set'):
|
||||
if ((not getattr(cls._fields[field], 'translate', False))
|
||||
or (Transaction().language
|
||||
== Config.get_language())):
|
||||
upd0.append(('"' + field + '"', '%s'))
|
||||
upd1.append(FIELDS[cls._fields[field]._type]
|
||||
.sql_format(values[field]))
|
||||
direct.append(field)
|
||||
else:
|
||||
upd_todo.append(field)
|
||||
if not hasattr(cls._fields[field], 'set'):
|
||||
if ((not getattr(cls._fields[field], 'translate', False))
|
||||
or (Transaction().language == Config.get_language())):
|
||||
upd0.append(('"' + field + '"', '%s'))
|
||||
upd1.append(FIELDS[cls._fields[field]._type]
|
||||
.sql_format(values[field]))
|
||||
direct.append(field)
|
||||
else:
|
||||
updend.append(field)
|
||||
upd_todo.append(field)
|
||||
|
||||
upd0.append(('write_uid', '%s'))
|
||||
upd0.append(('write_date', '%s'))
|
||||
@@ -894,24 +823,6 @@ class ModelSQL(ModelStorage):
|
||||
'FROM "' + cls._table + '" '
|
||||
'WHERE id = %s', (obj_id,))
|
||||
|
||||
for iname in cls._inherits:
|
||||
col = cls._inherits[iname]
|
||||
iids = []
|
||||
for i in range(0, len(ids), cursor.IN_MAX):
|
||||
sub_ids = ids[i:i + cursor.IN_MAX]
|
||||
red_sql, red_ids = reduce_ids('id', sub_ids)
|
||||
cursor.execute('SELECT DISTINCT "' + col + '" '
|
||||
'FROM "' + cls._table + '" WHERE ' + red_sql,
|
||||
red_ids)
|
||||
iids.extend([x[0] for x in cursor.fetchall()])
|
||||
|
||||
values2 = {}
|
||||
for val in updend:
|
||||
if cls._inherit_fields[val][0] == iname:
|
||||
values2[val] = values[val]
|
||||
IModel = pool.get(iname)
|
||||
IModel.write(IModel.browse(iids), values2)
|
||||
|
||||
cls._validate(records)
|
||||
|
||||
# Check for Modified Preorder Tree Traversal
|
||||
@@ -1330,41 +1241,6 @@ class ModelSQL(ModelStorage):
|
||||
domain = domain[:]
|
||||
cursor = Transaction().cursor
|
||||
|
||||
def column_get(model, field_name):
|
||||
field = model._fields.get(field_name)
|
||||
if not field:
|
||||
if not field_name in model._inherit_fields:
|
||||
raise Exception('ValidateError', 'Field "%s" doesn\'t '
|
||||
'exist on "%s"' % (field_name, model.__name__))
|
||||
parent_model = pool.get(model._inherit_fields[field_name][0])
|
||||
field = column_get(parent_model, field_name)
|
||||
return field
|
||||
|
||||
def get_model_for_field(model, field):
|
||||
if field in model._fields:
|
||||
return model
|
||||
else:
|
||||
parent_model = pool.get(model._inherit_fields[field][0])
|
||||
return get_model_for_field(parent_model, field)
|
||||
|
||||
def get_inherits_join(model, field):
|
||||
if field in model._fields:
|
||||
return []
|
||||
itable = pool.get(model._inherit_fields[field][0])
|
||||
table_query = ''
|
||||
table_arg = []
|
||||
if itable.table_query():
|
||||
table_query, table_args = model.table_query()
|
||||
table_query = '(' + table_query + ') AS '
|
||||
table_join = ('LEFT JOIN ' + table_query +
|
||||
'"' + itable._table + '" ON '
|
||||
'"%s".id = "%s"."%s"'
|
||||
% (itable._table, model._table,
|
||||
model._inherits[itable.__name__]))
|
||||
inherits = [(table_join, table_arg)]
|
||||
inherits.extend(get_inherits_join(itable, field))
|
||||
return inherits
|
||||
|
||||
for arg in domain:
|
||||
if arg[1] not in OPERATORS:
|
||||
raise Exception('ValidateError', 'Argument "%s" not supported'
|
||||
@@ -1373,21 +1249,13 @@ class ModelSQL(ModelStorage):
|
||||
joins = []
|
||||
while i < len(domain):
|
||||
fargs = domain[i][0].split('.', 1)
|
||||
if fargs[0] in cls._inherit_fields:
|
||||
inherit_joins = get_inherits_join(cls, fargs[0])
|
||||
for (table_join, table_arg) in inherit_joins:
|
||||
if table_join not in tables:
|
||||
tables.append(table_join)
|
||||
tables_args.extend(table_arg)
|
||||
|
||||
field = column_get(cls, fargs[0])
|
||||
table = get_model_for_field(cls, fargs[0])
|
||||
field = getattr(cls, fargs[0])
|
||||
table = cls
|
||||
if len(fargs) > 1:
|
||||
if field._type == 'many2one':
|
||||
Target = pool.get(field.model_name)
|
||||
m2o_search = [(fargs[1], domain[i][1], domain[i][2])]
|
||||
if ('active' in Target._fields
|
||||
or 'active' in Target._inherit_fields):
|
||||
if 'active' in Target._fields:
|
||||
m2o_search += [('active', 'in', (True, False))]
|
||||
if hasattr(field, 'search'):
|
||||
domain.extend([(fargs[0], 'in',
|
||||
@@ -1411,10 +1279,7 @@ class ModelSQL(ModelStorage):
|
||||
else:
|
||||
Relation = Target
|
||||
origin, target = field.field, 'id'
|
||||
if origin in Relation._fields:
|
||||
rev_field = Relation._fields[origin]
|
||||
else:
|
||||
rev_field = Relation._inherit_fields[origin][2]
|
||||
rev_field = Relation._fields[origin]
|
||||
if rev_field._type == 'reference':
|
||||
sql_type = FIELDS[
|
||||
cls.id._type].sql_type(cls.id)[0]
|
||||
@@ -1452,10 +1317,7 @@ class ModelSQL(ModelStorage):
|
||||
if Field.table_query():
|
||||
table_query, table_args = Field.table_query()
|
||||
table_query = '(' + table_query + ') AS '
|
||||
if field.field in Field._fields:
|
||||
rev_field = Field._fields[field.field]
|
||||
else:
|
||||
rev_field = Field._inherit_fields[field.field][2]
|
||||
rev_field = Field._fields[field.field]
|
||||
if rev_field._type == 'reference':
|
||||
sql_type = FIELDS[cls.id._type].sql_type(cls.id)[0]
|
||||
select = ('CAST(SPLIT_PART("%s", \',\', 2) AS %s)'
|
||||
@@ -1546,11 +1408,7 @@ class ModelSQL(ModelStorage):
|
||||
if Relation.table_query():
|
||||
table_query, table_args = Relation.table_query()
|
||||
table_query = '(' + table_query + ') AS '
|
||||
if field.origin in Relation._fields:
|
||||
origin_field = Relation._fields[field.origin]
|
||||
else:
|
||||
origin_field = \
|
||||
Relation._inherit_fields[field.origin][2]
|
||||
origin_field = Relation._fields[field.origin]
|
||||
if origin_field._type == 'reference':
|
||||
sql_type = FIELDS[cls.id._type].sql_type(cls.id)[0]
|
||||
select = ('CAST(SPLIT_PART("%s", \',\', 2) AS %s)'
|
||||
@@ -1650,8 +1508,7 @@ class ModelSQL(ModelStorage):
|
||||
if isinstance(domain[i][2], basestring):
|
||||
Field = pool.get(field.model_name)
|
||||
m2o_search = [('rec_name', domain[i][1], domain[i][2])]
|
||||
if ('active' in Field._fields
|
||||
or 'active' in Field._inherit_fields):
|
||||
if 'active' in Field._fields:
|
||||
m2o_search += [('active', 'in', (True, False))]
|
||||
res_ids = map(int, Field.search(m2o_search, order=[]))
|
||||
domain[i] = (domain[i][0], 'in', res_ids, table)
|
||||
@@ -1722,10 +1579,10 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
qu1, qu2 = [], []
|
||||
for arg in domain:
|
||||
table = get_model_for_field(cls, arg[0])
|
||||
if table == cls and len(arg) > 3:
|
||||
table = cls
|
||||
if len(arg) > 3:
|
||||
table = arg[3]
|
||||
column = column_get(table, arg[0])
|
||||
column = getattr(table, arg[0])
|
||||
if arg[1] in ('inselect', 'notinselect'):
|
||||
clause = 'IN'
|
||||
if arg[1] == 'notinselect':
|
||||
@@ -1914,61 +1771,6 @@ class ModelSQL(ModelStorage):
|
||||
tables.insert(0, table_join)
|
||||
return order_by, tables, tables_args
|
||||
|
||||
obj2 = None
|
||||
if obj._rec_name in obj._inherit_fields.keys():
|
||||
obj2 = pool.get(
|
||||
obj._inherit_fields[obj._rec_name][0])
|
||||
field_name = obj._rec_name
|
||||
|
||||
if obj._order_name in obj._inherit_fields.keys():
|
||||
obj2 = pool.get(
|
||||
obj._inherit_fields[obj._order_name][0])
|
||||
field_name = obj._order_name
|
||||
|
||||
if obj2 and field_name:
|
||||
table_name2 = obj2._table
|
||||
link_field2 = obj._inherits[obj2.__name__]
|
||||
order_by, tables, tables_args = \
|
||||
obj2._order_calc(field_name, otype)
|
||||
|
||||
table_join = ('LEFT JOIN "' + table_name + '" AS '
|
||||
'"' + table_name + '.' + link_field + '" ON '
|
||||
'"%s.%s".id = "%s"."%s"'
|
||||
% (table_name, link_field, cls._table, link_field))
|
||||
for i in range(len(order_by)):
|
||||
if table_name in order_by[i]:
|
||||
order_by[i] = order_by[i].replace(table_name,
|
||||
table_name + '.' + link_field)
|
||||
for i in range(len(tables)):
|
||||
if table_name in tables[i]:
|
||||
args = tables_args.pop(tables[i], [])
|
||||
tables[i] = tables[i].replace(table_name,
|
||||
table_name + '.' + link_field)
|
||||
tables_args[tables[i]] = args
|
||||
if table_join not in tables:
|
||||
tables.insert(0, table_join)
|
||||
tables_args[table_join] = []
|
||||
|
||||
table_join2 = ('LEFT JOIN "' + table_name2 + '" AS '
|
||||
'"' + table_name2 + '.' + link_field2 + '" ON '
|
||||
'"%s.%s".id = "%s.%s"."%s"'
|
||||
% (table_name2, link_field2, table_name, link_field,
|
||||
link_field2))
|
||||
for i in range(len(order_by)):
|
||||
if table_name2 in order_by[i]:
|
||||
order_by[i] = order_by[i].replace(table_name2,
|
||||
table_name2 + '.' + link_field2)
|
||||
for i in range(1, len(tables)):
|
||||
if table_name2 in tables[i]:
|
||||
args = tables_args.pop(tables[i], [])
|
||||
tables[i] = tables[i].replace(table_name2,
|
||||
table_name2 + '.' + link_field2)
|
||||
tables_args[tables[i]] = args
|
||||
if table_join2 not in tables:
|
||||
tables.insert(1, table_join2)
|
||||
tables_args[table_join2] = []
|
||||
return order_by, tables, tables_args
|
||||
|
||||
if (field_name in cls._fields
|
||||
and getattr(cls._fields[field_name], 'translate', False)):
|
||||
translation_table = ('ir_translation_%s_%s'
|
||||
@@ -2049,18 +1851,6 @@ class ModelSQL(ModelStorage):
|
||||
% (table_name, field_name, otype))
|
||||
return order_by, tables, tables_args
|
||||
|
||||
if field in cls._inherit_fields.keys():
|
||||
obj = pool.get(cls._inherit_fields[field][0])
|
||||
table_name = obj._table
|
||||
link_field = cls._inherits[obj.__name__]
|
||||
order_by, tables, tables_args = obj._order_calc(field, otype)
|
||||
table_join = ('LEFT JOIN "' + table_name + '" ON '
|
||||
'"%s".id = "%s"."%s"'
|
||||
% (table_name, cls._table, link_field))
|
||||
if table_join not in tables:
|
||||
tables.insert(0, table_join)
|
||||
return order_by, tables, tables_args
|
||||
|
||||
raise Exception('Error', 'Wrong field name (%s) for %s in order!' %
|
||||
(field, cls.__name__))
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ except ImportError:
|
||||
import StringIO
|
||||
|
||||
from decimal import Decimal
|
||||
from itertools import islice, ifilter, ifilterfalse, chain, izip
|
||||
from itertools import islice, ifilter, chain, izip
|
||||
from functools import reduce
|
||||
|
||||
from trytond.model import Model
|
||||
@@ -304,10 +304,7 @@ class ModelStorage(Model):
|
||||
field_defs[field_name]['relation'])
|
||||
relation_field = field_defs[field_name]['relation_field']
|
||||
if relation_field:
|
||||
if relation_field in Relation._fields:
|
||||
field = Relation._fields[relation_field]
|
||||
else:
|
||||
field = Relation._inherit_fields[relation_field][2]
|
||||
field = Relation._fields[relation_field]
|
||||
if field._type == 'reference':
|
||||
value = str(new_record)
|
||||
else:
|
||||
@@ -368,8 +365,7 @@ class ModelStorage(Model):
|
||||
records = cls.search(domain, offset=offset, limit=limit, order=order)
|
||||
|
||||
if not fields_names:
|
||||
fields_names = list(set(cls._fields.keys()
|
||||
+ cls._inherit_fields.keys()))
|
||||
fields_names = cls._fields.keys()
|
||||
if 'id' not in fields_names:
|
||||
fields_names.append('id')
|
||||
return cls.read(map(int, records), fields_names)
|
||||
@@ -380,10 +376,9 @@ class ModelStorage(Model):
|
||||
domain = reduce_domain(domain)
|
||||
# if the object has a field named 'active', filter out all inactive
|
||||
# records unless they were explicitely asked for
|
||||
if not (('active' in cls._fields
|
||||
or 'active' in cls._inherit_fields.keys())
|
||||
and (active_test
|
||||
and Transaction().context.get('active_test', True))):
|
||||
if not ('active' in cls._fields
|
||||
and active_test
|
||||
and Transaction().context.get('active_test', True)):
|
||||
return domain
|
||||
|
||||
def process(domain):
|
||||
@@ -417,8 +412,7 @@ class ModelStorage(Model):
|
||||
It is used by the Function field rec_name.
|
||||
'''
|
||||
rec_name = self._rec_name
|
||||
if (rec_name not in self._fields
|
||||
and rec_name not in self._inherit_fields):
|
||||
if rec_name not in self._fields:
|
||||
rec_name = 'id'
|
||||
return unicode(getattr(self, rec_name))
|
||||
|
||||
@@ -428,8 +422,7 @@ class ModelStorage(Model):
|
||||
Return a list of arguments for search on rec_name.
|
||||
'''
|
||||
rec_name = cls._rec_name
|
||||
if (rec_name not in cls._fields
|
||||
and rec_name not in cls._inherit_fields):
|
||||
if rec_name not in cls._fields:
|
||||
return []
|
||||
return [(rec_name,) + clause[1:]]
|
||||
|
||||
@@ -470,13 +463,7 @@ class ModelStorage(Model):
|
||||
break
|
||||
field_name = fields_tree[i]
|
||||
eModel = pool.get(value.__name__)
|
||||
if field_name in eModel._fields:
|
||||
field = eModel._fields[field_name]
|
||||
elif field_name in eModel._inherit_fields:
|
||||
field = eModel._inherit_fields[field_name][2]
|
||||
else:
|
||||
raise Exception('Field %s not available on object "%s"'
|
||||
% (field_name, eModel.__name__))
|
||||
field = eModel._fields[field_name]
|
||||
if field.states and 'invisible' in field.states:
|
||||
pyson_invisible = PYSONEncoder().encode(
|
||||
field.states['invisible'])
|
||||
@@ -833,13 +820,7 @@ class ModelStorage(Model):
|
||||
Function that checks if there is no recursion in the tree
|
||||
composed with parent as parent field name.
|
||||
'''
|
||||
if parent in cls._fields:
|
||||
parent_type = cls._fields[parent]._type
|
||||
elif parent in cls._inherit_fields:
|
||||
parent_type = cls._inherit_fields[parent][2]._type
|
||||
else:
|
||||
raise Exception('Field %s not available on object "%s"'
|
||||
% (parent, cls.__name__))
|
||||
parent_type = cls._fields[parent]._type
|
||||
|
||||
if parent_type not in ('many2one', 'many2many'):
|
||||
raise Exception(
|
||||
@@ -1161,8 +1142,7 @@ class ModelStorage(Model):
|
||||
pool = Pool()
|
||||
vals = {}
|
||||
for field in defaults.keys():
|
||||
fld_def = (field in cls._fields) and cls._fields[field] \
|
||||
or cls._inherit_fields[field][2]
|
||||
fld_def = cls._fields[field]
|
||||
if fld_def._type in ('many2one', 'one2one'):
|
||||
if isinstance(defaults[field], (list, tuple)):
|
||||
vals[field] = defaults[field][0]
|
||||
@@ -1223,13 +1203,10 @@ class ModelStorage(Model):
|
||||
self._local_cache.counter = counter
|
||||
|
||||
# fetch the definition of the field
|
||||
if name in self._fields:
|
||||
try:
|
||||
field = self._fields[name]
|
||||
elif name in self._inherit_fields:
|
||||
field = self._inherit_fields[name][2]
|
||||
else:
|
||||
raise AttributeError("'%s' Model has no attribute '%s'"
|
||||
% (self.__name__, name))
|
||||
except KeyError:
|
||||
raise AttributeError('"%s" has no attribute "%s"' % (self, name))
|
||||
|
||||
try:
|
||||
return self._local_cache[self.id][name]
|
||||
@@ -1248,17 +1225,12 @@ class ModelStorage(Model):
|
||||
if field.loading == 'eager':
|
||||
FieldAccess = Pool().get('ir.model.field.access')
|
||||
fread_accesses = {}
|
||||
for inherit_name in self._inherits:
|
||||
Inherit = Pool().get(inherit_name)
|
||||
fread_accesses.update(FieldAccess.check(inherit_name,
|
||||
Inherit._fields.keys(), 'read', access=True))
|
||||
fread_accesses.update(FieldAccess.check(self.__name__,
|
||||
self._fields.keys(), 'read', access=True))
|
||||
to_remove = set(x for x, y in fread_accesses.iteritems()
|
||||
if not y and x != name)
|
||||
|
||||
threshold = BROWSE_FIELD_TRESHOLD
|
||||
inherit_threshold = threshold - len(self._fields)
|
||||
|
||||
def not_cached(item):
|
||||
fname, field = item
|
||||
@@ -1274,17 +1246,6 @@ class ModelStorage(Model):
|
||||
fname, field = item
|
||||
return fname in self._fields
|
||||
|
||||
if inherit_threshold > 0:
|
||||
ifields = ((fname, field)
|
||||
for fname, (_, _, field) in
|
||||
self._inherit_fields.iteritems())
|
||||
ifields = ifilterfalse(overrided,
|
||||
ifilter(to_load,
|
||||
ifilter(not_cached, ifields)))
|
||||
ifields = islice(ifields, 0, inherit_threshold)
|
||||
ffields.update(ifields)
|
||||
threshold -= inherit_threshold
|
||||
|
||||
ifields = ifilter(to_load,
|
||||
ifilter(not_cached,
|
||||
self._fields.iteritems()))
|
||||
@@ -1294,11 +1255,7 @@ class ModelStorage(Model):
|
||||
# add datetime_field
|
||||
for field in ffields.values():
|
||||
if hasattr(field, 'datetime_field') and field.datetime_field:
|
||||
if field.datetime_field in self._fields:
|
||||
datetime_field = self._fields[field.datetime_field]
|
||||
else:
|
||||
datetime_field = self._inherit_fields[
|
||||
field.datetime_field][2]
|
||||
datetime_field = self._fields[field.datetime_field]
|
||||
ffields[field.datetime_field] = datetime_field
|
||||
|
||||
def filter_(id_):
|
||||
@@ -1393,10 +1350,7 @@ class ModelStorage(Model):
|
||||
if not self._values:
|
||||
return values
|
||||
for fname, value in self._values.iteritems():
|
||||
if fname in self._fields:
|
||||
field = self._fields[fname]
|
||||
else:
|
||||
field = self._inherit_fields[fname][2]
|
||||
field = self._fields[fname]
|
||||
if field._type in ('many2one', 'one2one', 'reference'):
|
||||
if value:
|
||||
if value.id < 0 and field._type != 'reference':
|
||||
@@ -1453,14 +1407,10 @@ class EvalEnvironment(dict):
|
||||
def __getitem__(self, item):
|
||||
if item.startswith('_parent_'):
|
||||
field = item[8:]
|
||||
if field in self._model._fields:
|
||||
model_name = self._model._fields[field].model_name
|
||||
else:
|
||||
model_name = self._model._inherit_fields[field][2].model_name
|
||||
model_name = self._model._fields[field].model_name
|
||||
ParentModel = Pool().get(model_name)
|
||||
return EvalEnvironment(getattr(self._record, field), ParentModel)
|
||||
if (item in self._model._fields
|
||||
or item in self._model._inherit_fields):
|
||||
if item in self._model._fields:
|
||||
value = getattr(self._record, item)
|
||||
if isinstance(value, Model):
|
||||
return value.id
|
||||
|
||||
@@ -327,24 +327,6 @@ class ModelView(Model):
|
||||
if field_to_remove in field.depends:
|
||||
fields_to_remove.append(name)
|
||||
|
||||
# Find field inherited without read access
|
||||
for inherit_name in cls._inherits:
|
||||
Inherit = pool.get(inherit_name)
|
||||
fread_accesses = FieldAccess.check(Inherit.__name__,
|
||||
Inherit._fields.keys(), 'read', access=True)
|
||||
fields_to_remove += list(x for x, y in fread_accesses.iteritems()
|
||||
if not y and x not in cls._fields.keys())
|
||||
|
||||
# Find relation field without read access
|
||||
for name, field in Inherit._fields.iteritems():
|
||||
if not check_relation(Inherit, field):
|
||||
fields_to_remove.append(name)
|
||||
|
||||
for name, field in Inherit._fields.iteritems():
|
||||
for field_to_remove in fields_to_remove:
|
||||
if field_to_remove in field.depends:
|
||||
fields_to_remove.append(name)
|
||||
|
||||
# Remove field without read access
|
||||
for field in fields_to_remove:
|
||||
for element in tree.xpath(
|
||||
@@ -372,26 +354,19 @@ class ModelView(Model):
|
||||
|
||||
if field_children:
|
||||
fields_def.setdefault(field_children, {'name': field_children})
|
||||
model, field = None, None
|
||||
if field_children in cls._fields:
|
||||
model = cls
|
||||
field = cls._fields[field_children]
|
||||
elif field_children in cls._inherit_fields:
|
||||
model_name, model, field = cls._inherit_fields[field_children]
|
||||
if model and field and field.model_name == model.__name__:
|
||||
fields_def.setdefault(field.field, {'name': field.field})
|
||||
|
||||
for field_name in fields_def.keys():
|
||||
if field_name in cls._fields:
|
||||
field = cls._fields[field_name]
|
||||
elif field_name in cls._inherit_fields:
|
||||
field = cls._inherit_fields[field_name][2]
|
||||
else:
|
||||
continue
|
||||
for depend in field.depends:
|
||||
fields_def.setdefault(depend, {'name': depend})
|
||||
|
||||
if ('active' in cls._fields) or ('active' in cls._inherit_fields):
|
||||
if 'active' in cls._fields:
|
||||
fields_def.setdefault('active', {'name': 'active'})
|
||||
|
||||
arch = etree.tostring(tree, encoding='utf-8', pretty_print=False)
|
||||
@@ -424,11 +399,7 @@ class ModelView(Model):
|
||||
if element.get(attr):
|
||||
fields_attrs.setdefault(element.get(attr), {})
|
||||
try:
|
||||
if element.get(attr) in cls._fields:
|
||||
field = cls._fields[element.get(attr)]
|
||||
else:
|
||||
field = cls._inherit_fields[element.get(
|
||||
attr)][2]
|
||||
field = cls._fields[element.get(attr)]
|
||||
if hasattr(field, 'model_name'):
|
||||
relation = field.model_name
|
||||
else:
|
||||
|
||||
@@ -459,6 +459,59 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="domain">[('groups', '=', None)]</field>
|
||||
<field name="rule_group" ref="rule_group_action_keyword"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_action_report">
|
||||
<field name="model" search="[('model', '=', 'ir.action.report')]"/>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_action_report1">
|
||||
<field name="domain">[('groups', 'in', [g.id for g in user.groups])]</field>
|
||||
<field name="rule_group" ref="rule_group_action_report"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_action_report2">
|
||||
<field name="domain">[('groups', '=', None)]</field>
|
||||
<field name="rule_group" ref="rule_group_action_report"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_action_act_window">
|
||||
<field name="model" search="[('model', '=', 'ir.action.act_window')]"/>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_action_act_window1">
|
||||
<field name="domain">[('groups', 'in', [g.id for g in user.groups])]</field>
|
||||
<field name="rule_group" ref="rule_group_action_act_window"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_action_act_window2">
|
||||
<field name="domain">[('groups', '=', None)]</field>
|
||||
<field name="rule_group" ref="rule_group_action_act_window"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_action_wizard">
|
||||
<field name="model" search="[('model', '=', 'ir.action.wizard')]"/>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_action_wizard1">
|
||||
<field name="domain">[('groups', 'in', [g.id for g in user.groups])]</field>
|
||||
<field name="rule_group" ref="rule_group_action_wizard"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_action_wizard2">
|
||||
<field name="domain">[('groups', '=', None)]</field>
|
||||
<field name="rule_group" ref="rule_group_action_wizard"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_action_url">
|
||||
<field name="model" search="[('model', '=', 'ir.action.url')]"/>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_action_url1">
|
||||
<field name="domain">[('groups', 'in', [g.id for g in user.groups])]</field>
|
||||
<field name="rule_group" ref="rule_group_action_url"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_action_url2">
|
||||
<field name="domain">[('groups', '=', None)]</field>
|
||||
<field name="rule_group" ref="rule_group_action_url"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action-res.group" id="act_module_install_upgrade_group_admin">
|
||||
<field name="action" ref="ir.act_module_install_upgrade"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
|
||||
@@ -90,11 +90,6 @@ def register():
|
||||
DictRequired,
|
||||
Singleton,
|
||||
URLObject,
|
||||
ModelInherits,
|
||||
ModelInheritsSubModel,
|
||||
ModelInheritsSubSubModel,
|
||||
ModelInheritsSubSubSubModel,
|
||||
ModelInheritsOverriddenFieldModel,
|
||||
ModelSQLRequiredField,
|
||||
MPTT,
|
||||
ImportDataBoolean,
|
||||
|
||||
+1
-50
@@ -3,9 +3,7 @@
|
||||
from trytond.model import ModelSingleton, ModelSQL, fields
|
||||
|
||||
__all__ = [
|
||||
'Singleton', 'URLObject', 'ModelInherits', 'ModelInheritsSubModel',
|
||||
'ModelInheritsSubSubModel', 'ModelInheritsSubSubSubModel',
|
||||
'ModelInheritsOverriddenFieldModel', 'ModelSQLRequiredField'
|
||||
'Singleton', 'URLObject', 'ModelSQLRequiredField',
|
||||
]
|
||||
|
||||
|
||||
@@ -25,53 +23,6 @@ class URLObject(ModelSQL):
|
||||
name = fields.Char('Name')
|
||||
|
||||
|
||||
class ModelInherits(ModelSQL):
|
||||
'Model Inherits'
|
||||
__name__ = 'test.model_inherits'
|
||||
|
||||
name = fields.Char('Name')
|
||||
|
||||
|
||||
class ModelInheritsSubModel(ModelSQL):
|
||||
'Model Inherits Sub-Model'
|
||||
__name__ = 'test.submodel'
|
||||
_inherits = {'test.model_inherits': 'parent_model'}
|
||||
|
||||
subfield = fields.Char('SubField')
|
||||
parent_model = fields.Many2One('test.model_inherits', 'Parent model',
|
||||
required=True)
|
||||
|
||||
|
||||
class ModelInheritsSubSubModel(ModelSQL):
|
||||
'Model Inherits Sub-Sub-Model'
|
||||
__name__ = 'test.subsubmodel'
|
||||
_inherits = {'test.submodel': 'parent_model'}
|
||||
|
||||
subsubfield = fields.Char('SubField')
|
||||
parent_model = fields.Many2One('test.submodel', 'Parent model',
|
||||
required=True)
|
||||
|
||||
|
||||
class ModelInheritsSubSubSubModel(ModelSQL):
|
||||
'Model Inherits Sub-Sub-Sub-Model'
|
||||
__name__ = 'test.subsubsubmodel'
|
||||
_inherits = {'test.subsubmodel': 'parent_model'}
|
||||
|
||||
subsubsubfield = fields.Char('SubField')
|
||||
parent_model = fields.Many2One('test.subsubmodel', 'Parent model',
|
||||
required=True)
|
||||
|
||||
|
||||
class ModelInheritsOverriddenFieldModel(ModelSQL):
|
||||
'Model Inherits Overridden Field Model'
|
||||
__name__ = 'test.overriddeninheritedfieldmodel'
|
||||
_inherits = {'test.subsubmodel': 'parent_model'}
|
||||
|
||||
subfield = fields.Integer('Overridden field')
|
||||
parent_model = fields.Many2One('test.subsubmodel', 'Parent model',
|
||||
required=True)
|
||||
|
||||
|
||||
class ModelSQLRequiredField(ModelSQL):
|
||||
'model with a required field'
|
||||
__name__ = 'test.modelsql'
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
import unittest
|
||||
from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT, \
|
||||
install_module
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class ModelInheritsTestCase(unittest.TestCase):
|
||||
'''
|
||||
Test ModelInheritSearch
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
install_module('test')
|
||||
self.parent = POOL.get('test.model_inherits')
|
||||
self.sub = POOL.get('test.submodel')
|
||||
self.subsub = POOL.get('test.subsubmodel')
|
||||
self.subsubsub = POOL.get('test.subsubsubmodel')
|
||||
self.overridden = POOL.get('test.overriddeninheritedfieldmodel')
|
||||
|
||||
def create_data(self):
|
||||
parent_id, = self.parent.create([{'name': 'parent'}])
|
||||
sub_id, = self.sub.create([{
|
||||
'name': 'sub',
|
||||
'subfield': 'level1',
|
||||
}])
|
||||
subsub_id, = self.subsub.create([{
|
||||
'name': 'subsub',
|
||||
'subfield': 'level2',
|
||||
'subsubfield': 'ssfcontent',
|
||||
}])
|
||||
subsubsub_id, = self.subsubsub.create([{
|
||||
'name': 'subsubsub',
|
||||
'subfield': 'level3',
|
||||
'subsubfield': 'ssfcontent2',
|
||||
'subsubsubfield': 'sssfcontent',
|
||||
}])
|
||||
overridden_id, = self.overridden.create([{
|
||||
'name': 'overridden',
|
||||
'subfield': 3,
|
||||
}])
|
||||
return (parent_id, sub_id, subsub_id, subsubsub_id, overridden_id)
|
||||
|
||||
def test0010selfsearch(self):
|
||||
'''
|
||||
Test searching on own field
|
||||
'''
|
||||
with Transaction().start(DB_NAME, USER,
|
||||
context=CONTEXT) as transaction:
|
||||
|
||||
(_parent_id, _sub_id, _subsub_id, subsubsub_id, overridden_id) = \
|
||||
self.create_data()
|
||||
|
||||
ids = self.subsubsub.search([
|
||||
('subsubsubfield', '=', 'sssfcontent'),
|
||||
])
|
||||
self.assertEqual(ids, [subsubsub_id])
|
||||
|
||||
transaction.cursor.rollback()
|
||||
|
||||
def test0020parentsearch(self):
|
||||
'''
|
||||
Test searching on parent field
|
||||
'''
|
||||
with Transaction().start(DB_NAME, USER,
|
||||
context=CONTEXT) as transaction:
|
||||
|
||||
(_parent_id, _sub_id, _subsub_id, subsubsub_id, overridden_id) = \
|
||||
self.create_data()
|
||||
|
||||
ids = self.subsubsub.search([('subsubfield', '=', 'ssfcontent2')])
|
||||
self.assertEqual(ids, [subsubsub_id])
|
||||
|
||||
ids = self.subsubsub.search([('subsubfield', '=', 'ssfcontent')])
|
||||
self.assertEqual(ids, [])
|
||||
|
||||
transaction.cursor.rollback()
|
||||
|
||||
def test0030granparentsearch(self):
|
||||
'''
|
||||
Test searching on granparent field
|
||||
'''
|
||||
with Transaction().start(DB_NAME, USER,
|
||||
context=CONTEXT) as transaction:
|
||||
|
||||
(_parent_id, _sub_id, _subsub_id, subsubsub_id, overridden_id) = \
|
||||
self.create_data()
|
||||
|
||||
ids = self.subsubsub.search([('subfield', '=', 'level3')])
|
||||
self.assertEqual(ids, [subsubsub_id])
|
||||
|
||||
ids = self.subsubsub.search([('subfield', '=', 'level1')])
|
||||
self.assertEqual(ids, [])
|
||||
|
||||
transaction.cursor.rollback()
|
||||
|
||||
def test0040greatgranparentsearch(self):
|
||||
'''
|
||||
Test searching on greatgranparent field
|
||||
'''
|
||||
with Transaction().start(DB_NAME, USER,
|
||||
context=CONTEXT) as transaction:
|
||||
|
||||
(_parent_id, _sub_id, _subsub_id, subsubsub_id, overridden_id) = \
|
||||
self.create_data()
|
||||
|
||||
ids = self.subsubsub.search([('name', '=', 'subsubsub')])
|
||||
self.assertEqual(ids, [subsubsub_id])
|
||||
|
||||
ids = self.subsubsub.search([('name', '=', 'parent')])
|
||||
self.assertEqual(ids, [])
|
||||
|
||||
transaction.cursor.rollback()
|
||||
|
||||
def test0050overriddenfieldsearch(self):
|
||||
'''
|
||||
Test searching on greatgranparent field
|
||||
'''
|
||||
with Transaction().start(DB_NAME, USER,
|
||||
context=CONTEXT) as transaction:
|
||||
|
||||
(_parent_id, _sub_id, _subsub_id, subsubsub_id, overridden_id) = \
|
||||
self.create_data()
|
||||
|
||||
ids = self.overridden.search([('subfield', '=', 3)])
|
||||
self.assertEqual(ids, [overridden_id])
|
||||
|
||||
transaction.cursor.rollback()
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(ModelInheritsTestCase)
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = suite()
|
||||
unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
@@ -255,8 +255,6 @@ def all_suite():
|
||||
suite_.addTests(test_mixins.suite())
|
||||
import trytond.tests.test_wizard as test_wizard
|
||||
suite_.addTests(test_wizard.suite())
|
||||
import trytond.tests.test_model_inherits as test_inherits
|
||||
suite_.addTests(test_inherits.suite())
|
||||
import trytond.tests.test_modelsql as test_modelsql
|
||||
suite_.addTests(test_modelsql.suite())
|
||||
import trytond.tests.test_cache as test_cache
|
||||
|
||||
Reference in new issue
Block a user