From 16e741268ccbf48b3a6e5301dbfb114c2d48d14c Mon Sep 17 00:00:00 2001 From: sebalix Date: Wed, 29 Jun 2016 10:02:40 +0200 Subject: [PATCH 1/5] [FIX] base_multi_image - New storage backend 'Filestore' to link an existing attachment record + Fix the 'pre_init_hook_for_submodules()' hook to extract the images from the ir_attachment table for binary fields initialized with the 'attachment=True' parameter --- base_multi_image/hooks.py | 45 ++++++++++++++++++++------- base_multi_image/models/image.py | 21 ++++++++++++- base_multi_image/views/image_view.xml | 6 ++++ 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/base_multi_image/hooks.py b/base_multi_image/hooks.py index 74d29ed55..140d00d48 100644 --- a/base_multi_image/hooks.py +++ b/base_multi_image/hooks.py @@ -22,23 +22,44 @@ def pre_init_hook_for_submodules(cr, model, field): """ env = api.Environment(cr, SUPERUSER_ID, dict()) with cr.savepoint(): + table = env[model]._table + column_exists = table_has_column(cr, table, field) + # Extract the binary content directly from the table + if column_exists: + extract_query = """ + SELECT id, %%s, 'db', %(field)s + FROM %(table)s + WHERE %(field)s IS NOT NULL + """ % {"table": table, "field": field} + image_field = 'file_db_store' + # Extract the binary content from the ir_attachment table + else: + extract_query = """ + SELECT res_id, res_model, 'filestore', id + FROM ir_attachment + WHERE res_field='%(field)s' AND res_model='%(model)s' + """ % {"model": model, "field": field} + image_field = 'attachment_id' + + cr.execute(extract_query) cr.execute( """ INSERT INTO base_multi_image_image ( owner_id, owner_model, storage, - file_db_store + %s ) - SELECT - id, - %%s, - 'db', - %(field)s - FROM - %(table)s - WHERE - %(field)s IS NOT NULL - """ % {"table": env[model]._table, "field": field}, - (model,) + %s + """ % (image_field, extract_query) ) + + +def table_has_column(cr, table, field): + query = """ + SELECT %(field)s + FROM information_schema.columns + WHERE table_name=%(table)s and column_name=%(field)s; + """ + cr.execute(query, {'table': table, 'field': field}) + return bool(cr.fetchall()) diff --git a/base_multi_image/models/image.py b/base_multi_image/models/image.py index 187cbbf90..a5689c31c 100644 --- a/base_multi_image/models/image.py +++ b/base_multi_image/models/image.py @@ -28,7 +28,8 @@ class Image(models.Model): owner_model = fields.Char( required=True) storage = fields.Selection( - [('url', 'URL'), ('file', 'OS file'), ('db', 'Database')], + [('url', 'URL'), ('file', 'OS file'), ('db', 'Database'), + ('filestore', 'Filestore')], required=True) name = fields.Char( 'Image title', @@ -37,6 +38,9 @@ class Image(models.Model): extension = fields.Char( 'File extension', readonly=True) + attachment_id = fields.Many2one( + 'ir.attachment', + string='Attachment') file_db_store = fields.Binary( 'Image stored in database', filters='*.png,*.jpg,*.gif') @@ -84,6 +88,10 @@ class Image(models.Model): "default_owner_%s" % f not in self.env.context for f in ("id", "model")) + @api.multi + def _get_image_from_filestore(self): + return self.attachment_id.datas + @api.multi def _get_image_from_db(self): return self.file_db_store @@ -157,6 +165,11 @@ class Image(models.Model): self.name, self.extension = os.path.splitext(self.filename) self.name = self._make_name_pretty(self.name) + @api.onchange('attachment_id') + def _onchange_attachmend_id(self): + if self.attachment_id: + self.name = self.attachment_id.res_name + @api.constrains('storage', 'url') def _check_url(self): if self.storage == 'url' and not self.url: @@ -174,3 +187,9 @@ class Image(models.Model): if self.storage == 'db' and not self.file_db_store: raise exceptions.ValidationError( 'You must provide an attached file for the image.') + + @api.constrains('storage', 'attachment_id') + def _check_store(self): + if self.storage == 'filestore' and not self.attachment_id: + raise exceptions.ValidationError( + 'You must provide an attachment for the image.') diff --git a/base_multi_image/views/image_view.xml b/base_multi_image/views/image_view.xml index b4b925714..e7bd342d2 100644 --- a/base_multi_image/views/image_view.xml +++ b/base_multi_image/views/image_view.xml @@ -50,6 +50,12 @@ 'required': [('storage', '=', 'db')], }" filename="filename"/> + Date: Wed, 29 Jun 2016 12:28:26 +0200 Subject: [PATCH 2/5] [IMP] base_multi_image - Select only images as attachments --- base_multi_image/models/image.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base_multi_image/models/image.py b/base_multi_image/models/image.py index a5689c31c..d01ffbd20 100644 --- a/base_multi_image/models/image.py +++ b/base_multi_image/models/image.py @@ -40,7 +40,8 @@ class Image(models.Model): readonly=True) attachment_id = fields.Many2one( 'ir.attachment', - string='Attachment') + string='Attachment', + domain="[('index_content', '=', 'image')]") file_db_store = fields.Binary( 'Image stored in database', filters='*.png,*.jpg,*.gif') From 414509caad814fb76bfcf64aace70bc88318afcf Mon Sep 17 00:00:00 2001 From: sebalix Date: Thu, 30 Jun 2016 22:08:30 +0200 Subject: [PATCH 3/5] [FIX] base_multi_image - Clean up + updated comments --- base_multi_image/hooks.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/base_multi_image/hooks.py b/base_multi_image/hooks.py index 140d00d48..55496df40 100644 --- a/base_multi_image/hooks.py +++ b/base_multi_image/hooks.py @@ -24,7 +24,7 @@ def pre_init_hook_for_submodules(cr, model, field): with cr.savepoint(): table = env[model]._table column_exists = table_has_column(cr, table, field) - # Extract the binary content directly from the table + # fields.Binary(), extract the binary content directly from the table if column_exists: extract_query = """ SELECT id, %%s, 'db', %(field)s @@ -32,7 +32,7 @@ def pre_init_hook_for_submodules(cr, model, field): WHERE %(field)s IS NOT NULL """ % {"table": table, "field": field} image_field = 'file_db_store' - # Extract the binary content from the ir_attachment table + # fields.Binary(attachment=True), get the ir_attachment record ID else: extract_query = """ SELECT res_id, res_model, 'filestore', id @@ -40,8 +40,6 @@ def pre_init_hook_for_submodules(cr, model, field): WHERE res_field='%(field)s' AND res_model='%(model)s' """ % {"model": model, "field": field} image_field = 'attachment_id' - - cr.execute(extract_query) cr.execute( """ INSERT INTO base_multi_image_image ( From cf32f411c3829227575b664757124d92a6b84039 Mon Sep 17 00:00:00 2001 From: sebalix Date: Thu, 30 Jun 2016 22:15:24 +0200 Subject: [PATCH 4/5] [FIX] base_multi_image - Make validation error messages translatable --- base_multi_image/models/image.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base_multi_image/models/image.py b/base_multi_image/models/image.py index d01ffbd20..0da993558 100644 --- a/base_multi_image/models/image.py +++ b/base_multi_image/models/image.py @@ -175,22 +175,22 @@ class Image(models.Model): def _check_url(self): if self.storage == 'url' and not self.url: raise exceptions.ValidationError( - 'You must provide an URL for the image.') + _('You must provide an URL for the image.')) @api.constrains('storage', 'path') def _check_path(self): if self.storage == 'file' and not self.path: raise exceptions.ValidationError( - 'You must provide a file path for the image.') + _('You must provide a file path for the image.')) @api.constrains('storage', 'file_db_store') def _check_store(self): if self.storage == 'db' and not self.file_db_store: raise exceptions.ValidationError( - 'You must provide an attached file for the image.') + _('You must provide an attached file for the image.')) @api.constrains('storage', 'attachment_id') def _check_store(self): if self.storage == 'filestore' and not self.attachment_id: raise exceptions.ValidationError( - 'You must provide an attachment for the image.') + _('You must provide an attachment for the image.')) From 2bddb2fc0061dcd8661c87b239077f717a9df6d2 Mon Sep 17 00:00:00 2001 From: sebalix Date: Thu, 30 Jun 2016 22:16:40 +0200 Subject: [PATCH 5/5] [FIX] base_multi_image - Fix method name --- base_multi_image/models/image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base_multi_image/models/image.py b/base_multi_image/models/image.py index 0da993558..dfb5501d3 100644 --- a/base_multi_image/models/image.py +++ b/base_multi_image/models/image.py @@ -190,7 +190,7 @@ class Image(models.Model): _('You must provide an attached file for the image.')) @api.constrains('storage', 'attachment_id') - def _check_store(self): + def _check_attachment_id(self): if self.storage == 'filestore' and not self.attachment_id: raise exceptions.ValidationError( _('You must provide an attachment for the image.'))