Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- +def better_reference(field_name, field_string, selection=None, set_index=True):
- + class ReferenceMixin(ModelSQL):
- + '''
- + This mixin adds a new reference function field with the
- + "field_name" parameter as field name and "field_string" as string.
- + It uses "selection" as the selection method. If not set, it will
- + accept all models.
- + If "set_index" is True, an index on the id part will be created.
- + This index should be enough for most cases since filtering only on
- + the model part is not a standard use case, and there should not be
- + enough differente models to justify a composite index.
- +
- + It also create two "real fields" :
- +
- + - A char field to hold the model data
- + - An int field to store the target id
- +
- + This field has a getter / setter / searcher and should be usable
- + the same way standard reference fields are, except the database
- + model will be far easier to query.
- + '''
- + @classmethod
- + def setter_void(cls, *args, **kwargs):
- + pass
- +
- + if selection is None:
- + @classmethod
- + def get_models(cls):
- + return Pool().get('ir.property').models_get()
- +
- + setattr(ReferenceMixin, '_reference_mixin_get_all_models', get_models)
- + selection = '_reference_mixin_get_all_models'
- +
- + real_field = fields.Function(
- + fields.Reference(field_string, selection),
- + 'getter_%s' % field_name, 'setter_void',
- + 'searcher_%s' % field_name)
- + model_field = fields.Char(field_string + ' Model')
- + id_field = fields.Integer(field_string + ' Id', select=set_index)
- +
- + model_part = '%s_model' % field_name
- + id_part = '%s_id' % field_name
- +
- + def getter(self, name):
- + model = getattr(self, model_part, None)
- + if model is None:
- + return None
- + return '%s,%i' % (getattr(self, model_part), getattr(self, id_part))
- +
- + @classmethod
- + def searcher(cls, name, clause):
- + name, operator, value = clause[:3]
- + Operator = fields.SQL_OPERATORS[operator]
- + if '.' not in name:
- + # Simple char field. We could just generate the query by
- + # concatening model and id part, but this would not use any indexes
- + # so be less optimized
- + if clause[1:3] in (('=', ''), ('=', None)):
- + return (id_part, '=', None)
- + if clause[1:3] in (('!=', ''), ('!=', None)):
- + return (id_part, '!=', None)
- + if operator in ('like', 'ilike', 'not like', 'not ilike'):
- + table = cls.__table__()
- + return ('id', 'in', table.select(table.id,
- + where=Operator(Concat(
- + Concat(Column(table, model_part), ','),
- + Cast(Column(table, id_part), 'VARCHAR')),
- + value)))
- + if operator == '=':
- + operator = 'in'
- + if operator == '!=':
- + operator = 'not in'
- + if not isinstance(value, (list, tuple)):
- + value = [value]
- + if operator == 'in':
- + return ['OR'] + [[
- + (model_part, '=', x.split(',')[0]),
- + (id_part, '=', int(x.split(',')[1]))]
- + for x in value]
- + if operator == 'not in':
- + return [['OR',
- + (model_part, '!=', x.split(',')[0]),
- + (id_part, '!=', int(x.split(',')[1]))]
- + for x in value]
- + raise NotImplementedError
- +
- + # Actually easier, we just forward the query to the target model, then
- + # filter out the ids, see field/reference.py -> convert_domain
- + target = clause[3]
- + Target = Pool().get(target)
- + name, target_name = name.split('.', 1)
- + target_domain = [(target_name,) + tuple(clause[1:3]) +
- + tuple(clause[4:])]
- + if 'active' in Target._fields:
- + target_domain.append(('active', 'in', [True, False]))
- + query = Target.search(target_domain, order=[], query=True)
- + return [(model_part, '=', target), (id_part, 'in', query)]
- +
- + @classmethod
- + def create(cls, vlist):
- + for data in vlist:
- + if field_name in data:
- + value = data.pop(field_name)
- + if value in (None, ''):
- + data[model_part] = None
- + data[id_part] = None
- + continue
- + model, id = value.split(',')
- + data[model_part] = model
- + data[id_part] = int(id)
- + return super(ReferenceMixin, cls).create(vlist)
- +
- + @classmethod
- + def write(cls, *args):
- + actions = iter(args)
- + for _, data in zip(actions, actions):
- + if field_name in data:
- + value = data.pop(field_name)
- + if value in (None, ''):
- + data[model_part] = None
- + data[id_part] = None
- + continue
- + model, id = value.split(',')
- + data[model_part] = model
- + data[id_part] = int(id)
- + return super(ReferenceMixin, cls).write(*args)
- +
- + setattr(ReferenceMixin, field_name, real_field)
- + setattr(ReferenceMixin, model_part, model_field)
- + setattr(ReferenceMixin, id_part, id_field)
- + setattr(ReferenceMixin, 'getter_%s' % field_name, getter)
- + setattr(ReferenceMixin, 'searcher_%s' % field_name, searcher)
- + setattr(ReferenceMixin, 'create', create)
- + setattr(ReferenceMixin, 'write', write)
- +
- + return ReferenceMixin
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement