diff --git a/addons/product/models/product.py b/addons/product/models/product.py index 704feebb00e..6987b612f98 100644 --- a/addons/product/models/product.py +++ b/addons/product/models/product.py @@ -207,6 +207,12 @@ class ProductProduct(models.Model): for record in self: record.can_image_1024_be_zoomed = record.can_image_variant_1024_be_zoomed if record.image_variant_1920 else record.product_tmpl_id.can_image_1024_be_zoomed + def _get_placeholder_filename(self, field): + image_fields = ['image_%s' % size for size in [1920, 1024, 512, 256, 128]] + if field in image_fields: + return 'product/static/img/placeholder.png' + return super()._get_placeholder_filename(field) + def init(self): """Ensure there is at most one active variant for each combination. diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index 3586370cf63..d1e14b0176e 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -1219,6 +1219,12 @@ class ProductTemplate(models.Model): self.ensure_one() return self.env.company + def _get_placeholder_filename(self, field): + image_fields = ['image_%s' % size for size in [1920, 1024, 512, 256, 128]] + if field in image_fields: + return 'product/static/img/placeholder.png' + return super()._get_placeholder_filename(field) + def get_single_product_variant(self): """ Method used by the product configurator to check if the product is configurable or not. diff --git a/addons/product/static/img/placeholder.png b/addons/product/static/img/placeholder.png new file mode 100644 index 00000000000..61efef843bd Binary files /dev/null and b/addons/product/static/img/placeholder.png differ diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 8c153e2f50d..32a5b7a0f77 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1367,7 +1367,9 @@ class View(http.Controller): class Binary(http.Controller): @staticmethod - def placeholder(image='placeholder.png'): + def placeholder(image=False): + if not image: + image = 'placeholder.png' image_path = image.lstrip('/').split('/') if '/' in image else ['web', 'static', 'img', image] with tools.file_open(get_resource_path(*image_path), 'rb') as fd: return fd.read() @@ -1460,7 +1462,10 @@ class Binary(http.Controller): if status in [301, 304] or (status != 200 and download): return request.env['ir.http']._response_by_status(status, headers, image_base64) if not image_base64: - placeholder_content = Binary.placeholder() + placeholder_filename = False + if model in request.env: + placeholder_filename = request.env[model]._get_placeholder_filename(field) + placeholder_content = Binary.placeholder(image=placeholder_filename) # Since we set a placeholder for any missing image, the status must be 200. In case one # wants to configure a specific 404 page (e.g. though nginx), a 404 status will cause # troubles. diff --git a/odoo/models.py b/odoo/models.py index 8ba0579e171..51f7879acee 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -6461,6 +6461,16 @@ Fields: return result + def _get_placeholder_filename(self, field): + """ Returns the filename of the placeholder to use, + set on web/static/img by default, or the + complete path to access it (eg: module/path/to/image.png). + + If a falsy value is returned, Binary.placeholder() will use + the default placeholder 'web/static/img/placeholder.png'. + """ + return False + def _populate_factories(self): """ Generates a factory for the different fields of the model.