diff --git a/odoo/addons/test_new_api/models/test_new_api.py b/odoo/addons/test_new_api/models/test_new_api.py index 45398e74df6..a574b5b8514 100644 --- a/odoo/addons/test_new_api/models/test_new_api.py +++ b/odoo/addons/test_new_api/models/test_new_api.py @@ -941,7 +941,10 @@ class BinarySvg(models.Model): name = fields.Char(required=True) image_attachment = fields.Binary(attachment=True) image_wo_attachment = fields.Binary(attachment=False) - + image_wo_attachment_related = fields.Binary( + "image wo attachment", related="image_wo_attachment", + store=True, attachment=False, + ) class MonetaryBase(models.Model): _name = 'test_new_api.monetary_base' diff --git a/odoo/addons/test_new_api/tests/test_web_save.py b/odoo/addons/test_new_api/tests/test_web_save.py index 7d17e61848c..41678a61a40 100644 --- a/odoo/addons/test_new_api/tests/test_web_save.py +++ b/odoo/addons/test_new_api/tests/test_web_save.py @@ -1,6 +1,8 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.tests.common import TransactionCase +from odoo.addons.base.tests.test_mimetypes import SVG, JPG + class TestWebSave(TransactionCase): @@ -36,3 +38,39 @@ class TestWebSave(TransactionCase): # Modify an existing record, with unity specification result = person.web_save({'name': 'lpe'}, {'display_name': {}}) self.assertEqual(result, [{'id': person.id, 'display_name': 'lpe'}]) + + def test_web_save_computed_stored_binary(self): + [result] = self.env['test_new_api.binary_svg'].web_save( + {'name': 'test', 'image_wo_attachment': SVG}, + {'image_wo_attachment': {}, 'image_wo_attachment_related': {}}, + ) + self.assertEqual(result['image_wo_attachment'], '400 bytes') # From PostgreSQL + self.assertEqual(result['image_wo_attachment_related'], b'400.00 bytes') # From human_size + + # check cache values + record = self.env['test_new_api.binary_svg'].browse(result['id']) + self.assertEqual(record.image_wo_attachment, SVG) + self.assertEqual(record.image_wo_attachment, record.image_wo_attachment_related) + + # check database values + self.env.invalidate_all() + self.assertEqual(record.image_wo_attachment, SVG) + self.assertEqual(record.image_wo_attachment, record.image_wo_attachment_related) + + # check web_save() on existing record + self.env.invalidate_all() + [result] = record.web_save( + {'image_wo_attachment': JPG}, + {'image_wo_attachment': {}, 'image_wo_attachment_related': {}}, + ) + self.assertEqual(result['image_wo_attachment'], '727 bytes') # From PostgreSQL + self.assertEqual(result['image_wo_attachment_related'], b'727.00 bytes') # From human_size + + # check cache values + self.assertEqual(record.image_wo_attachment, JPG.encode()) + self.assertEqual(record.image_wo_attachment, record.image_wo_attachment_related) + + # check database values + self.env.invalidate_all() + self.assertEqual(record.image_wo_attachment, JPG.encode()) + self.assertEqual(record.image_wo_attachment, record.image_wo_attachment_related) diff --git a/odoo/fields.py b/odoo/fields.py index 86af1dea939..5a1943064c6 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -2406,18 +2406,18 @@ class Binary(Field): for record_no_bin_size, record in zip(records_no_bin_size, records): try: value = cache.get(record_no_bin_size, self) - try: - value = base64.b64decode(value) - except (TypeError, binascii.Error): - pass + # don't decode non-attachments to be consistent with pg_size_pretty + if not (self.store and self.column_type): + with contextlib.suppress(TypeError, binascii.Error): + value = base64.b64decode(value) try: if isinstance(value, (bytes, _BINARY)): value = human_size(len(value)) except (TypeError): pass cache_value = self.convert_to_cache(value, record) - dirty = self.column_type and self.store and any(records._ids) - cache.set(record, self, cache_value, dirty=dirty) + # the dirty flag is independent from this assignment + cache.set(record, self, cache_value, check_dirty=False) except CacheMiss: pass else: