diff options
| author | Raphael Collet <rco@openerp.com> | 2017-01-19 16:29:29 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-01-19 16:29:29 +0100 |
| commit | b0646f9d2c983481f20bea31f8f6427bbfccb245 (patch) | |
| tree | f3e22dd4dc6ab5c09331af50e30c71616fcd0048 /addons/base_sparse_field/models/fields.py | |
| parent | cb90aeade61c8b19ee0313a948ef2fbbf44b2380 (diff) | |
[REF] move support for sparse fields into a separate module (#15070)
This removal has led to a necessary refactoring:
- make the setup of field attributes extensible;
- make the instantiation of custom fields extensible;
- delegate model and field reflection to `ir.model` and `ir.model.fields`;
- move the implementation of sparse and serialized fields to module `base_sparse_field`;
Diffstat (limited to 'addons/base_sparse_field/models/fields.py')
| -rw-r--r-- | addons/base_sparse_field/models/fields.py | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/addons/base_sparse_field/models/fields.py b/addons/base_sparse_field/models/fields.py new file mode 100644 index 00000000000..cb1e1981193 --- /dev/null +++ b/addons/base_sparse_field/models/fields.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- + +import json + +from odoo import fields + + +def monkey_patch(cls): + """ Return a method decorator to monkey-patch the given class. """ + def decorate(func): + name = func.__name__ + func.super = getattr(cls, name, None) + setattr(cls, name, func) + return func + return decorate + + +# +# Implement sparse fields by monkey-patching fields.Field +# + +fields.Field.__doc__ += """ + + .. _field-sparse: + + .. rubric:: Sparse fields + + Sparse fields have a very small probability of being not null. Therefore + many such fields can be serialized compactly into a common location, the + latter being a so-called "serialized" field. + + :param sparse: the name of the field where the value of this field must + be stored. +""" + +@monkey_patch(fields.Field) +def _get_attrs(self, model, name): + attrs = _get_attrs.super(self, model, name) + if attrs.get('sparse'): + # by default, sparse fields are not stored and not copied + attrs['store'] = False + attrs['copy'] = attrs.get('copy', False) + attrs['compute'] = self._compute_sparse + if not attrs.get('readonly'): + attrs['inverse'] = self._inverse_sparse + return attrs + +@monkey_patch(fields.Field) +def _compute_sparse(self, records): + for record in records: + values = record[self.sparse] + record[self.name] = values.get(self.name) + if self.relational: + for record in records: + record[self.name] = record[self.name].exists() + +@monkey_patch(fields.Field) +def _inverse_sparse(self, records): + for record in records: + values = record[self.sparse] + value = self.convert_to_read(record[self.name], record, use_name_get=False) + if value: + if values.get(self.name) != value: + values[self.name] = value + record[self.sparse] = values + else: + if self.name in values: + values.pop(self.name) + record[self.sparse] = values + + +# +# Definition and implementation of serialized fields +# + +class Serialized(fields.Field): + """ Serialized fields provide the storage for sparse fields. """ + type = 'serialized' + _slots = { + 'prefetch': False, # not prefetched by default + } + column_type = ('text', 'text') + + def convert_to_column(self, value, record): + return json.dumps(value) + + def convert_to_cache(self, value, record, validate=True): + # cache format: dict + value = value or {} + return value if isinstance(value, dict) else json.loads(value) + +fields.Serialized = Serialized |
