The protection prevents fields to be invalidated/recomputed on some records.
This mechanism is useful against accidental cache invalidation when computing
or inversing fields. It also prevents to trigger the recomputation of fields
before and/or after their inversion.
Add a test on stored field with compute and inverse methods: the test checks
how many times the compute and inverse methods are invoked in several cases.
Essentially, the field should not be recomputed when it is written.
There's really no reason to limit group_operator to numeric fields and Postgres's flexible aggregate make the ability to aggregate on non-numeric fields (and/or non-numerically)
* moves group_operator to Field
* adds a default value of `sum` on integer, float and monetary fields
* in read_group, filters on fields with a group operator rather than by
type (also allow id fields, since Id doesn't have a group_operator by
default it will be ignored anyway) (sequence is still specifically
excluded for now because they're usually regular Integer fields)
Closes#12372
Add a class for float objects that carry their precision digits, use it for the
value of monetary fields in record cache, and serialize them as expected for
the database.
Our usage of domain on fields One2many seems to trigger an obscure behaviour on
onchange.
With the following (simplified) config:
Message(models.Model):
_name = 'test_new_api.message'
important = fields.Boolean('Important')
Discussion(models.Model):
_name = 'test_new_api.discussion'
name = fields.Char('Name')
important_emails = fields.One2Many('test_new_api.emailmessage', 'discussion',
domain=[('important', '=', True)])
Email(models.Model):
_name = 'test_new_api.emailmessage'
_inherits = {'test_new_api.message': 'message'}
discussion = fields.Many2one('test_new_api.discussion', 'Discussion')
message = fields.Many2one('test_new_api.message', 'Message')
Steps:
- We change 'name' on discussion, triggers an `onchange()` call
- we ends up filling cache on virtual record (on secondary fields, we calling
record.mapped('important_emails.important'))
- we get a cache miss ('important' field not provided, only 'important_emails' ids,
i.e with no change on existing records)
- we fill the cache, this mark 'important' field as modified
- because of commit 5676d81 and because 'important' is that case is a related (i.e
computed) field we triggers cache recomputation
- as there is no way to recompute 'important_emails' for virtual record (no real
ID) we ends up with empty 'important_emails' generating removal of existing records.
=> Finally changing any value for 'test_new_api.discussion' that trigger an onchange
will always reset 'important_emails' to empty
Fixed by Raphael Collet <rco@odoo.com>, and test by Xavier Alt <xal@odoo.com>.
Invalidate the cache of a x2many field when any of the fields appearing in its
domain is modified. Use the invalidation triggers mechanism for that purpose.
When traversing relational fields as superuser, you end up with a recordset for
which only a subset is accessible to the current user. An earlier fix to this
issue completely dropped the `related_sudo` feature; change its implementation
to keep the feature.
Make the following statements add secondary records (values of relational fields)
in the prefetching object of ``self``:
self.read(fields)
self.partner_id # implicitly invokes read()
This makes sure that traversing relational fields on records automatically
feeds the prefetching of secondary records.
The prefetching now has a more intuitive and controllable model: every
recordset is linked to a "prefetch object" that tells which record ids to
prefetch for any model. The prefetch object of a given recordset is shared
with the records obtained by iteration and relational field access. All other
operations instantiate recordsets with a fresh prefetch object.
records = model.browse(ids)
assert records._prefetch is not model._prefetch
for record in records:
assert record._prefetch is records._prefetch
assert record.relation._prefetch is record._prefetch
The cache data format has been split between a cache format and a record format
(returned by accessing a field on a record). We have the following converters:
ANY FORMAT
|
| convert_to_cache
v
CACHE FORMAT
|
| convert_to_record
v
RECORD FORMAT
|
| convert_to_read
| convert_to_write
| convert_to_onchange
| convert_to_export
| convert_to_display_name
v
OTHER FORMATS
Modify the API of the converter methods to make them uniform (pass value and
record), and adapt their documentation.
Do not strip class by default on html fields, this was an error. Currently
only mail_message body field should not contain classes. Indeed as external
content can be stored through the mail gateway we do not want to keep the
classes.
Added the support of strip_classes, like the already existing strip_style
parameter of html fields.. This parameter is missing but allow full
customization of html fields.
Also fixed the call to the sanitizer in fields. Indeed the strict mode is
set to False. When not in strict mode the classes are never stripped whatever
the value of strip_classes.
Sanitizer is now called always in strict mode to ensure the sanitize process
is correct and really take into account strip_style and strip_classes.
This fix is done in master due to possible side effects and possible behavior
changes that are not welcomed in stable versions.
Those cases can now appear, since a model inheriting (with `_inherit`) from
another model can observe those extra fields from its parent model's class.