In `__getattr__`, remove the test on accessing `_attrs`. This situation should
never happen, since the attribute `_attrs` is set in method `__init__()`.
Introduce slots on all field classes for common attributes; slots take much
less memory than a `__dict__`. The other attributes are stored in a dictionary
`_attrs`; all fields with an empty value for `_attrs` (common case) share the
same empty dictionary. This saves quite some memory (around 4.5Mb per
registry), given the number of field instances created for a registry.
Another mechanism is used for the default values of attributes, since slots
cannot be assigned on classes.
The optimization consists in using tuples for attributes `inverse_fields`,
`computed_fields` and `_triggers`, and to let them share their value when it is
empty, which is common. This saves around 1.8Mb per registry.
This saves about 400Kb per registry by not allocating those lists, which are in
most cases empty. The removal of the attribute will also simplify a bit the
management of free attributes.
The computed value of parameter digits is no longer stored into fields and
columns; instead the value is recomputed everytime it is needed. Note that
performance is not an issue, since the method `get_precision` of model
'decimal.precision' is cached by the orm. This simplifies the management of
digits on fields and saves about 300Kb per registry.
For public-facing HTML content provided by the user,
`<style>` tags and `style` attributes should be stripped
automatically, as they can easily be abused to deface
pages for abusive users and spammers.
<style> tags were already stripped, the optional `strip_style`
for fields.html enables the automatic stripping of style
attributes.
This is opt-in because custom style attributes are still
desirable in trusted HTML fields.
Improve the performance of `name_get()` on many2one field values by making sure
that the records on which `name_get` is invoked are prefetched in cache. This
is not automatic, because `name_get` is invoked on records in another
environment (sudo mode): the prefetching in the original environment should be
reproduced in the other environment.
The implementation was based on the ill-defined method `same_parameters()` that
compares arguments based on a heuristic. Instead, we now create a new column
and check whether it is equivalent to `self` by comparing the arguments
returned by `to_field_args()`. If that is the case, `self` is reused instead
of the new column.
The code refactoring also fixes the column reuse which was broken by the
introduction of the parameter `compute` in commit 9333c62. Indeed, with that
parameter, `same_parameters()` always returned False, since old-api columns do
not have that parameter by default. The parameter has been renamed to
`_computed_field`, and is no longer passed for creating columns.
When overriding a field defined as a function field, the field must either
create a corresponding column that is not a fields.function (if stored), or
have no corresponding column (if not stored).
Idea: look up for the model's fields in method `_setup_base()` instead of
method `__init__()`. This does not make a significant difference when
installing or upgrading modules, but when simply loading a registry, the
(expensive) field lookup is done once per model instead of once per class.
The mechanism to determine the table and column names of new-api many2many
fields only worked for many2many fields created from old-api many2many columns!
This fixes#4851.
This reverts commit 8cd2cc8910.
It turned out that forcing recomputing fields as user admin breaks some
existing behavior. Instead, we make the recomputation as user admin explicit
by adding compute_sudo=True in the field's definition.
This log line is only useful when debugging registry
loading, a limited use case now that Odoo 8 is stable.
It makes the debug log more difficult to read and causes
a small performance penalty when debug[_rpc] is on.
(+0.2s i.e. 10% extra time for loading a registry with 47
modules on a core i5-4200U machine)
The model setup sometimes misses entries in _inherit_fields and _all_columns.
This is because those dictionaries are computed from parent models which are
not guaranteed to be completely set up: sometimes a parent field is only
partially set up, and columns are missing (they are generated from fields after
their setup).
To avoid this bug, the setup has been split in three phases:
(1) determine all inherited and custom fields on models;
(2) setup fields, except for recomputation triggers, and generate columns;
(3) add recomputation triggers and complete the setup of the model.
Making these three phases explicit brings good invariants:
- when setting up a field, all models know all their fields;
- when adding recomputation triggers, you know that fields have been set up.
This is necessary for supporting old-api sparse and serialized fields. Without
this, old-api serialized fields are broken because they cannot be converted to
new-api fields.
This closes#4571
For models using a datetime field as name (hr.attendance for instance), the user timezone wasn't applied in the display name.
Therefore, in the breadcrumb, the datetime was different than in the form if the user had another timezone than UTC.
This rev. is related to 27d8cb843b, but is for the 8.0 api
We are aware we introduce a tiny change of API (method signature change), which we normally prohibit, but considering the really low level of the method, the fact it is probably not ovveriden by any other modules and the fact there is no cleaner way to correct this, we are making an exception.
Non-setup fields could cause problems in two places:
- when traversing the chain of fields in related fields;
- when adding recomputation triggers on inverse fields
Both issues are fixed by this patch.
During a migration of database, it is possible that some custom field
("x_", state is 'manual') are relational to model from a module that is
not provided.
Note: this used to work in Odoo 7.0 but crashed in 8.0.
Closes#3877
* use static imports in java examples to make them terser
* inline ``domain`` in java and php example to make examples more
self-contained
* try to extend/improve Model.write's docstring
* add convenience kwarg to fields_get, mostly for user-driven
introspection
Closes#3689
When an onchange returns a change in a 2many field line (a '1' tuple, update), avoid to return all fields of the *2many field but only the altered field.
Otherwise, the web client regard all the fields of the 2many as dirty, and try to write on all fields (even if the value is the same, thus)
opw-615062
There was an issue in _setup_fields(): the method invokes _inherits_reload(),
which recomputes inherited fields, and invokes itself recursively on children
models. This may be problematic if the children models have already been set
up.
This optimization avoids recursive calls of method _inherits_reload(). In
_setup_fields(), first all parent models are set up, then their fields are
inspected to determine inherited fields, and their setup is done. This scheme
guarantees that inherited fields are computed once per model.
The old-api model._all_columns contains information about model._columns and
inherited columns. This dictionary is missing new-api computed non-stored
fields, and the new field objects provide a more readable api...
This commit contains the following changes:
- adapt several methods of BaseModel to use fields instead of columns and
_all_columns
- copy all semantic-free attributes of related fields from their source
- add attribute 'group_operator' on integer and float fields
- base, base_action_rule, crm, edi, hr, mail, mass_mailing, pad,
payment_acquirer, share, website, website_crm, website_mail: simply use
_fields instead of _all_columns
- base, decimal_precision, website: adapt qweb rendering methods to use fields
instead of columns
Clarify the semantics of field attributes:
- field.store is True when the field is actually stored in the database;
- field.column is the column corresponding to field or None.
The various field definitions correspond to:
- new-style stored field: field.store and field.column
- new-style non-stored field: not field.store and not field.column
- old-style regular field: field.store and field.column
- old-style function field: not field.store and field.column
Because some parameters of a field may be determined during its setup, we have
to update the corresponding column after the setup, and recompute _all_columns
to make it consistent.
One can infer related=True on a non-stored related field if all fields on the
path are related. This cannot be done if the related field is stored: when you
create a record, the database row is created first, and the related field is
computed and stored afterwards. Making the field required in that case would
trigger a non-null constraint violation.
This is a memory optimization: it reduces the memory footprint of each
registry. We have observed a reduction of 10Mb on a database with modules crm,
sale, purchase, stock.
The setup of relational fields may be problematic, as they may refer to unknown
models via custom relational fields. In a partial setup, do not try to skip
the field setup, but let it go and silently catch any exception if it crashes.
In the case of custom fields, the field's parameters were set up without the
field being present in the class hierarchy. Because of this, the parameter
inheritance mechanism was missing the field itself. As a consequence, custom
selection fields ended up without selection, for instance :-/
Compute methods could give results that should not be considered as default
values. For instance, a related field usually defaults to a null value, which
is then set to the field with its inverse method by create(). This may violate
a non-null constraint if the original field is required. Therefore, compute
methods are no longer used to determine default values.